diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index d52701f..47a2764 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -58,15 +58,15 @@ jobs: go-version: stable - name: Show Go environment outputs run: | - echo "go-path: ${{ steps.setup-go.outputs.go-path }}" - echo "go-bin: ${{ steps.setup-go.outputs.go-bin }}" + echo "GOPATH: ${{ steps.setup-go.outputs.GOPATH }}" + echo "GOBIN: ${{ steps.setup-go.outputs.GOBIN }}" echo "go-bin-path: ${{ steps.setup-go.outputs.go-bin-path }}" - echo "go-root: ${{ steps.setup-go.outputs.go-root }}" - echo "go-cache: ${{ steps.setup-go.outputs.go-cache }}" - echo "go-mod-cache: ${{ steps.setup-go.outputs.go-mod-cache }}" - echo "go-os: ${{ steps.setup-go.outputs.go-os }}" - echo "go-arch: ${{ steps.setup-go.outputs.go-arch }}" - echo "go-tool-dir: ${{ steps.setup-go.outputs.go-tool-dir }}" + echo "GOROOT: ${{ steps.setup-go.outputs.GOROOT }}" + echo "GOCACHE: ${{ steps.setup-go.outputs.GOCACHE }}" + echo "GOMODCACHE: ${{ steps.setup-go.outputs.GOMODCACHE }}" + echo "GOOS: ${{ steps.setup-go.outputs.GOOS }}" + echo "GOARCH: ${{ steps.setup-go.outputs.GOARCH }}" + echo "GOTOOLDIR: ${{ steps.setup-go.outputs.GOTOOLDIR }}" aliases-arch: runs-on: ${{ matrix.os }} diff --git a/__tests__/setup-go.test.ts b/__tests__/setup-go.test.ts index c595855..c1946bd 100644 --- a/__tests__/setup-go.test.ts +++ b/__tests__/setup-go.test.ts @@ -17,6 +17,7 @@ import goTestManifest from './data/versions-manifest.json' with {type: 'json'}; import type {IGoVersion} from '../src/installer.js'; import type {IToolRelease} from '@actions/tool-cache'; +import {GO_ENV_OUTPUTS} from '../src/constants.js'; const httpClientGetJson = jest.fn(); @@ -697,17 +698,19 @@ describe('setup-go', () => { it('sets an output for each exposed variable', () => { main.setGoEnvOutputs(goEnv); - expect(setOutputSpy).toHaveBeenCalledWith('go-path', goEnv.GOPATH); - expect(setOutputSpy).toHaveBeenCalledWith('go-bin', ''); - expect(setOutputSpy).toHaveBeenCalledWith('go-root', goEnv.GOROOT); - expect(setOutputSpy).toHaveBeenCalledWith('go-cache', goEnv.GOCACHE); - expect(setOutputSpy).toHaveBeenCalledWith( - 'go-mod-cache', - goEnv.GOMODCACHE - ); - expect(setOutputSpy).toHaveBeenCalledWith('go-os', goEnv.GOOS); - expect(setOutputSpy).toHaveBeenCalledWith('go-arch', goEnv.GOARCH); - expect(setOutputSpy).toHaveBeenCalledWith('go-tool-dir', goEnv.GOTOOLDIR); + expect(GO_ENV_OUTPUTS).toEqual([ + 'GOPATH', + 'GOBIN', + 'GOROOT', + 'GOCACHE', + 'GOMODCACHE', + 'GOOS', + 'GOARCH', + 'GOTOOLDIR' + ]); + for (const name of GO_ENV_OUTPUTS) { + expect(setOutputSpy).toHaveBeenCalledWith(name, goEnv[name] ?? ''); + } }); it('falls back to $GOPATH/bin when GOBIN is empty', () => { @@ -735,7 +738,7 @@ describe('setup-go', () => { main.setGoEnvOutputs({...goEnv, GOPATH}); - expect(setOutputSpy).toHaveBeenCalledWith('go-path', GOPATH); + expect(setOutputSpy).toHaveBeenCalledWith('GOPATH', GOPATH); expect(setOutputSpy).toHaveBeenCalledWith( 'go-bin-path', '/Users/testuser/go/bin' @@ -745,7 +748,7 @@ describe('setup-go', () => { it('leaves variables missing from go env -json empty', () => { main.setGoEnvOutputs({}); - expect(setOutputSpy).toHaveBeenCalledWith('go-path', ''); + expect(setOutputSpy).toHaveBeenCalledWith('GOPATH', ''); expect(setOutputSpy).toHaveBeenCalledWith('go-bin-path', ''); }); }); diff --git a/action.yml b/action.yml index 919604e..79299e5 100644 --- a/action.yml +++ b/action.yml @@ -26,23 +26,23 @@ outputs: description: 'The installed Go version. Useful when given a version range as input.' cache-hit: description: 'A boolean value to indicate if a cache was hit' - go-path: + GOPATH: description: 'The value of `go env GOPATH`.' - go-bin: + GOBIN: description: 'The value of `go env GOBIN`.' go-bin-path: description: 'The base Go binary directory: `GOBIN`, otherwise `bin` under the first `GOPATH` entry.' - go-root: + GOROOT: description: 'The value of `go env GOROOT`.' - go-cache: + GOCACHE: description: 'The value of `go env GOCACHE`, the build cache directory.' - go-mod-cache: + GOMODCACHE: description: 'The value of `go env GOMODCACHE`, the module cache directory.' - go-os: + GOOS: description: 'The value of `go env GOOS`, the target OS in Go notation (linux, darwin, windows).' - go-arch: + GOARCH: description: 'The value of `go env GOARCH`, the target architecture in Go notation (amd64, arm64).' - go-tool-dir: + GOTOOLDIR: description: 'The value of `go env GOTOOLDIR`, the directory holding the toolchain binaries.' runs: using: 'node24' diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index adfef81..edde4be 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -95641,16 +95641,18 @@ var State; var Outputs; (function (Outputs) { Outputs["CacheHit"] = "cache-hit"; - Outputs["GoPath"] = "go-path"; - Outputs["GoBin"] = "go-bin"; Outputs["GoBinPath"] = "go-bin-path"; - Outputs["GoRoot"] = "go-root"; - Outputs["GoCache"] = "go-cache"; - Outputs["GoModCache"] = "go-mod-cache"; - Outputs["GoOs"] = "go-os"; - Outputs["GoArch"] = "go-arch"; - Outputs["GoToolDir"] = "go-tool-dir"; })(Outputs || (Outputs = {})); +const GO_ENV_OUTPUTS = (/* unused pure expression or super */ null && ([ + 'GOPATH', + 'GOBIN', + 'GOROOT', + 'GOCACHE', + 'GOMODCACHE', + 'GOOS', + 'GOARCH', + 'GOTOOLDIR' +])); ;// CONCATENATED MODULE: ./src/package-managers.ts const supportedPackageManagers = { diff --git a/dist/setup/index.js b/dist/setup/index.js index 2aa3b6d..e40b1e1 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -100441,16 +100441,18 @@ var State; var Outputs; (function (Outputs) { Outputs["CacheHit"] = "cache-hit"; - Outputs["GoPath"] = "go-path"; - Outputs["GoBin"] = "go-bin"; Outputs["GoBinPath"] = "go-bin-path"; - Outputs["GoRoot"] = "go-root"; - Outputs["GoCache"] = "go-cache"; - Outputs["GoModCache"] = "go-mod-cache"; - Outputs["GoOs"] = "go-os"; - Outputs["GoArch"] = "go-arch"; - Outputs["GoToolDir"] = "go-tool-dir"; })(Outputs || (Outputs = {})); +const GO_ENV_OUTPUTS = [ + 'GOPATH', + 'GOBIN', + 'GOROOT', + 'GOCACHE', + 'GOMODCACHE', + 'GOOS', + 'GOARCH', + 'GOTOOLDIR' +]; ;// CONCATENATED MODULE: ./src/package-managers.ts const supportedPackageManagers = { @@ -100674,24 +100676,14 @@ function readGoEnv(goPath) { return undefined; } } -const goEnvOutputs = [ - [Outputs.GoPath, 'GOPATH'], - [Outputs.GoBin, 'GOBIN'], - [Outputs.GoRoot, 'GOROOT'], - [Outputs.GoCache, 'GOCACHE'], - [Outputs.GoModCache, 'GOMODCACHE'], - [Outputs.GoOs, 'GOOS'], - [Outputs.GoArch, 'GOARCH'], - [Outputs.GoToolDir, 'GOTOOLDIR'] -]; function setGoEnvOutputs(goEnv) { - for (const [output, variable] of goEnvOutputs) { - setOutput(output, goEnv[variable] ?? ''); + for (const name of GO_ENV_OUTPUTS) { + setOutput(name, goEnv[name] ?? ''); } - setOutput(Outputs.GoBinPath, goEnv['GOBIN'] || goPathBin(goEnv)); + setOutput(Outputs.GoBinPath, goEnv.GOBIN || goPathBin(goEnv)); } function goPathBin(goEnv) { - const goPath = (goEnv['GOPATH'] ?? '').split((external_path_default()).delimiter)[0]; + const goPath = (goEnv.GOPATH ?? '').split((external_path_default()).delimiter)[0]; return goPath ? external_path_default().join(goPath, 'bin') : ''; } async function addBinToPath() { diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index ef67034..0e3efa5 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -427,17 +427,17 @@ jobs: Once Go is on the `PATH`, the action exposes the most commonly needed `go env` variables as outputs, so workflows don't have to query them in duplicated `bash`/`pwsh` steps — one expression works on Linux, macOS, and Windows. The values are a snapshot from setup time: anything a later step changes, such as setting `GOOS`/`GOARCH` to cross-compile, is not reflected. -| Output | `go env` variable | Notes | -| --- | --- | --- | -| `go-path` | `GOPATH` | Go workspace root; `bin` and `pkg/mod` live under it | -| `go-bin` | `GOBIN` | Go 1.27+ reports an implicit `$GOPATH/bin` default; earlier releases are empty unless `GOBIN` is set | -| `go-bin-path` | `GOBIN` or `$GOPATH/bin` | The base Go binary directory, using the first `GOPATH` entry. Cross-compiled binaries go one level deeper, in `$GOPATH/bin/$GOOS_$GOARCH` | -| `go-root` | `GOROOT` | Installation directory of the Go toolchain in use | -| `go-cache` | `GOCACHE` | Build cache directory | -| `go-mod-cache` | `GOMODCACHE` | Module cache directory | -| `go-os` | `GOOS` | Go notation (`linux`, `darwin`, `windows`), unlike `runner.os` | -| `go-arch` | `GOARCH` | Go notation (`amd64`, `arm64`), unlike `runner.arch` or the `x64` in the action's cache key | -| `go-tool-dir` | `GOTOOLDIR` | Holds `compile`, `link`, `vet` and the other toolchain binaries | +| Output | Notes | +| --- | --- | +| `GOPATH` | Go workspace root; `bin` and `pkg/mod` live under it | +| `GOBIN` | Go 1.27+ reports an implicit `$GOPATH/bin` default; earlier releases are empty unless `GOBIN` is set | +| `go-bin-path` | The base Go binary directory (`GOBIN` or `$GOPATH/bin`), using the first `GOPATH` entry. Cross-compiled binaries go one level deeper, in `$GOPATH/bin/$GOOS_$GOARCH` | +| `GOROOT` | Installation directory of the Go toolchain in use | +| `GOCACHE` | Build cache directory | +| `GOMODCACHE` | Module cache directory | +| `GOOS` | Go notation (`linux`, `darwin`, `windows`), unlike `runner.os` | +| `GOARCH` | Go notation (`amd64`, `arm64`), unlike `runner.arch` or the `x64` in the action's cache key | +| `GOTOOLDIR` | Holds `compile`, `link`, `vet` and the other toolchain binaries | ```yaml steps: @@ -445,13 +445,13 @@ steps: id: setup-go with: go-version: '1.25.5' - - run: echo "Modules are cached in ${{ steps.setup-go.outputs.go-mod-cache }}" + - run: echo "Modules are cached in ${{ steps.setup-go.outputs.GOMODCACHE }}" ``` Quote `go-bin-path` in shell commands, since it may contain spaces. Variables without a dedicated output are not exposed; run `go env ` in a step when you need one. > [!NOTE] -> These outputs need Go 1.9 or newer (`go env -json`); on older releases the action logs a message, leaves them unset and does not fail. `go-cache` needs Go 1.10 and `go-mod-cache` needs Go 1.15. +> These outputs need Go 1.9 or newer (`go env -json`); on older releases the action logs a message, leaves them unset and does not fail. `GOCACHE` needs Go 1.10 and `GOMODCACHE` needs Go 1.15. ## Custom download URL diff --git a/src/constants.ts b/src/constants.ts index 685a563..1c49cb3 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -5,13 +5,19 @@ export enum State { export enum Outputs { CacheHit = 'cache-hit', - GoPath = 'go-path', - GoBin = 'go-bin', - GoBinPath = 'go-bin-path', - GoRoot = 'go-root', - GoCache = 'go-cache', - GoModCache = 'go-mod-cache', - GoOs = 'go-os', - GoArch = 'go-arch', - GoToolDir = 'go-tool-dir' + GoBinPath = 'go-bin-path' } + +export const GO_ENV_OUTPUTS = [ + 'GOPATH', + 'GOBIN', + 'GOROOT', + 'GOCACHE', + 'GOMODCACHE', + 'GOOS', + 'GOARCH', + 'GOTOOLDIR' +] as const; + +export type GoEnvVar = (typeof GO_ENV_OUTPUTS)[number]; +export type GoEnv = Partial>; diff --git a/src/main.ts b/src/main.ts index 86487fa..b1c9a49 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,7 +10,7 @@ import cp from 'child_process'; import fs from 'fs'; import os from 'os'; import {Architecture} from './types.js'; -import {Outputs} from './constants.js'; +import {GO_ENV_OUTPUTS, GoEnv, Outputs} from './constants.js'; export async function run() { try { @@ -125,7 +125,7 @@ export async function run() { } } -export function readGoEnv(goPath: string): Record | undefined { +export function readGoEnv(goPath: string): GoEnv | undefined { try { const rawGoEnv = cp.execFileSync(goPath, ['env', '-json'], { encoding: 'utf8', @@ -141,7 +141,7 @@ export function readGoEnv(goPath: string): Record | undefined { throw new Error("'go env -json' did not return a JSON object"); } - return parsed as Record; + return parsed as GoEnv; } catch (error) { core.info( `Unable to read 'go env -json', the Go environment outputs will not be set: ${ @@ -152,27 +152,16 @@ export function readGoEnv(goPath: string): Record | undefined { } } -const goEnvOutputs: ReadonlyArray<[Outputs, string]> = [ - [Outputs.GoPath, 'GOPATH'], - [Outputs.GoBin, 'GOBIN'], - [Outputs.GoRoot, 'GOROOT'], - [Outputs.GoCache, 'GOCACHE'], - [Outputs.GoModCache, 'GOMODCACHE'], - [Outputs.GoOs, 'GOOS'], - [Outputs.GoArch, 'GOARCH'], - [Outputs.GoToolDir, 'GOTOOLDIR'] -]; - -export function setGoEnvOutputs(goEnv: Record): void { - for (const [output, variable] of goEnvOutputs) { - core.setOutput(output, goEnv[variable] ?? ''); +export function setGoEnvOutputs(goEnv: GoEnv): void { + for (const name of GO_ENV_OUTPUTS) { + core.setOutput(name, goEnv[name] ?? ''); } - core.setOutput(Outputs.GoBinPath, goEnv['GOBIN'] || goPathBin(goEnv)); + core.setOutput(Outputs.GoBinPath, goEnv.GOBIN || goPathBin(goEnv)); } -function goPathBin(goEnv: Record): string { - const goPath = (goEnv['GOPATH'] ?? '').split(path.delimiter)[0]; +function goPathBin(goEnv: GoEnv): string { + const goPath = (goEnv.GOPATH ?? '').split(path.delimiter)[0]; return goPath ? path.join(goPath, 'bin') : ''; }