Compare commits

..

2 Commits

Author SHA1 Message Date
aparnajyothi-y
19bb51245e V4 - Add workflow file for publishing releases to immutable action package (#583)
* Add Publish Immutable Action to V4

* file name update
2025-04-17 10:36:03 -05:00
Priya Gupta
cd53bc84d5 v4 - upgrade @actions/cache (#578)
* Upgrade-actions/cache for v4

* audit fix

* Replaced macos-latest with macos-13
2025-04-13 22:11:47 -05:00
78 changed files with 20090 additions and 22080 deletions

View File

@@ -7,7 +7,7 @@ assignees: ''
---
<!--- Please direct any generic questions related to actions to our support community forum at https://github.com/orgs/community/discussions/categories/actions --->
<!--- Please direct any generic questions related to actions to our support community forum at https://github.community/c/code-to-cloud/github-actions/41 --->
<!--- Before opening up a new bug report, please make sure to check for similar existing issues -->
**Description:**

View File

@@ -5,7 +5,7 @@ title: ''
labels: feature request, needs triage
assignees: ''
---
<!--- Please direct any generic questions related to actions to our support community forum at https://github.com/orgs/community/discussions/categories/actions --->
<!--- Please direct any generic questions related to actions to our support community forum at https://github.community/c/code-to-cloud/github-actions/41 --->
<!--- Before opening up a new feature request, please make sure to check for similar existing issues and pull requests -->
**Description:**

View File

@@ -1,22 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
# Enable version updates for npm
- package-ecosystem: 'npm'
# Look for `package.json` and `lock` files in the `root` directory
directory: '/'
# Check the npm registry for updates every day (weekdays)
schedule:
interval: 'weekly'
# Enable version updates for GitHub Actions
- package-ecosystem: 'github-actions'
# Workflow files stored in the default location of `.github/workflows`
# You don't need to specify `/.github/workflows` for `directory`. You can use `directory: "/"`.
directory: '/'
schedule:
interval: 'weekly'

View File

@@ -14,5 +14,3 @@ jobs:
call-basic-validation:
name: Basic validation
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
with:
node-version: '24.x'

View File

@@ -15,5 +15,3 @@ jobs:
call-check-dist:
name: Check dist/
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
with:
node-version: '24.x'

View File

@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checking out
uses: actions/checkout@v5
uses: actions/checkout@v4
- name: Publish
id: publish
uses: actions/publish-immutable-action@v0.0.4

View File

@@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Update the ${{ env.TAG_NAME }} tag
uses: actions/publish-action@v0.3.0
uses: actions/publish-action@v0.2.2
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

View File

@@ -18,9 +18,9 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: Setup Go Stable
uses: ./
with:
@@ -33,9 +33,9 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: Setup Go oldStable
uses: ./
with:
@@ -48,16 +48,14 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
os: [ubuntu-latest, windows-latest, macos-latest]
version: [stable, oldstable]
architecture: [x64, x32]
exclude:
- os: macos-latest
architecture: x32
- os: macos-13
architecture: x32
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: Setup Go ${{ matrix.version }} ${{ matrix.architecture }}
uses: ./
with:
@@ -72,17 +70,11 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest, macos-13]
go: [1.21.13, 1.22.8, 1.23.2]
include:
- os: windows-latest
go: 1.20.14
exclude:
- os: windows-latest
go: 1.23.2
os: [macos-latest, windows-latest, ubuntu-latest]
go: [1.17, 1.18, 1.19]
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v3
- name: setup-go ${{ matrix.go }}
uses: ./
@@ -98,10 +90,10 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
go-version: ['1.20', '1.21', '1.22', '1.23']
os: [ubuntu-latest, windows-latest, macos-latest]
go-version: [1.16, 1.17]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: Setup Go and check latest
uses: ./
with:
@@ -115,15 +107,15 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
os: [ubuntu-latest, windows-latest, macos-13]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: Setup Go and check latest
uses: ./
with:
go-version-file: __tests__/data/go.mod
- name: verify go
run: __tests__/verify-go.sh 1.20.14
run: __tests__/verify-go.sh 1.14
shell: bash
go-version-file-with-gowork:
@@ -131,27 +123,28 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: Setup Go and check latest
uses: ./
with:
go-version-file: __tests__/data/go.work
- name: verify go
run: __tests__/verify-go.sh 1.21
run: __tests__/verify-go.sh 1.19
shell: bash
setup-versions-from-manifest:
name: Setup ${{ matrix.go }} ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest, macos-13]
go: [1.20.14, 1.21.10, 1.22.8, 1.23.2]
os: [macos-13, windows-latest, ubuntu-latest]
go: [1.12.16, 1.13.11, 1.14.3]
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v3
- name: setup-go ${{ matrix.go }}
uses: ./
@@ -163,15 +156,19 @@ jobs:
shell: bash
setup-versions-from-dist:
name: Setup ${{ matrix.go }} ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-13]
go: [1.11.12]
os: [macos-13, windows-latest, ubuntu-latest]
go: [1.11.12, 1.8.6]
exclude:
- os: macos-13
go: 1.8.6
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v3
- name: setup-go ${{ matrix.go }}
uses: ./
@@ -187,23 +184,14 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
go-version: [1.20.14, 1.21, 1.22, 1.23]
include:
- os: macos-latest
architecture: arm64
- os: ubuntu-latest
architecture: x64
- os: windows-latest
architecture: x64
- os: macos-13
architecture: x64
os: [ubuntu-latest, windows-latest, macos-latest]
go-version: [1.16, 1.17]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: Setup Go and check latest
uses: ./
with:
go-version: ${{ matrix.go-version }}
architecture: ${{ matrix.architecture }}
architecture: x64
- name: Verify Go
run: go version

View File

@@ -19,7 +19,7 @@ jobs:
cache: [false, true]
go: [1.20.1]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: 'Setup ${{ matrix.cache }}, cache: ${{ matrix.go }}'
uses: ./
@@ -88,7 +88,7 @@ jobs:
matrix:
cache: [false, true]
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: 'Setup default go, cache: ${{ matrix.cache }}'
uses: ./
@@ -112,25 +112,3 @@ jobs:
exit 1
fi
shell: bash
hostedtoolcache:
name: 'Validate if hostedtoolcache works as expected'
runs-on: windows-latest
strategy:
matrix:
cache: [false]
go: [1.20.1]
steps:
- uses: actions/checkout@v5
- name: 'Setup ${{ matrix.go }}, cache: ${{ matrix.cache }}'
uses: ./
with:
go-version: ${{ matrix.go }}
cache: ${{ matrix.cache }}
- name: 'Setup ${{ matrix.go }}, cache: ${{ matrix.cache }} (from hostedtoolcache)'
uses: ./
with:
go-version: ${{ matrix.go }}
cache: ${{ matrix.cache }}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
.licenses/npm/form-data-4.0.0.dep.yml generated Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
.licenses/npm/tslib-2.3.1.dep.yml generated Normal file

Binary file not shown.

Binary file not shown.

126
README.md
View File

@@ -8,21 +8,26 @@ This action sets up a go environment for use in actions by:
- Optionally downloading and caching a version of Go by version and adding to `PATH`.
- Registering problem matchers for error output.
# Breaking changes in V6
# V4
- Improve toolchain handling to ensure more reliable and consistent toolchain selection and management.
- Upgraded from node20 to node24.
> Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. [See Release Notes](https://github.com/actions/runner/releases/tag/v2.327.1)
The V4 edition of the action offers:
For more details, see the full release notes on the [releases page](https://github.com/actions/setup-go/releases/tag/v6.0.0)
- Enabled caching by default
# V5
The action will try to enable caching unless the `cache` input is explicitly set to false.
The V5 edition of the action offers:
Please see "[Caching dependency files and build outputs](https://github.com/actions/setup-go#caching-dependency-files-and-build-outputs)" for more information.
- Upgraded Node.js runtime from node16 to node20
# V3
See full release notes on the [releases page](https://github.com/actions/setup-go/releases).
The V3 edition of the action offers:
- Adds `GOBIN` to the `PATH`
- Proxy support
- Check latest version
- Caching packages dependencies
- stable and oldstable aliases
- Bug Fixes (including issues around version matching and semver)
The action will first check the local cache for a version match. If a version is not found locally, it will pull it from
the `main` branch of the [go-versions](https://github.com/actions/go-versions/blob/main/versions-manifest.json)
@@ -37,8 +42,8 @@ Matching by [semver spec](https://github.com/npm/node-semver):
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '^1.13.1' # The Go version to download (if necessary) and use.
- run: go version
@@ -46,8 +51,8 @@ steps:
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '>=1.17.0'
- run: go version
@@ -60,13 +65,12 @@ steps:
> ```
>
> The recommendation is based on the YAML parser's behavior, which interprets non-wrapped values as numbers and, in the case of version 1.20, trims it down to 1.2, which may not be very obvious.
Matching an unstable pre-release:
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.18.0-rc.1' # The Go version to download (if necessary) and use.
- run: go version
@@ -74,8 +78,8 @@ steps:
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.16.0-beta.1' # The Go version to download (if necessary) and use.
- run: go version
@@ -89,8 +93,8 @@ See [action.yml](action.yml)
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.16.1' # The Go version to download (if necessary) and use.
- run: go run hello.go
@@ -110,8 +114,8 @@ want the most up-to-date Go version to always be used.
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.14'
check-latest: true
@@ -131,8 +135,8 @@ set to `true`
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: 'stable'
- run: go run hello.go
@@ -140,8 +144,8 @@ steps:
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: 'oldstable'
- run: go run hello.go
@@ -155,7 +159,7 @@ The `cache` input is optional, and caching is turned on by default.
The action defaults to search for the dependency file - go.sum in the repository root, and uses its hash as a part of
the cache key. Use `cache-dependency-path` input for cases when multiple dependency files are used, or they are located
in different subdirectories. The input supports glob patterns.
in different subdirectories.
If some problem that prevents success caching happens then the action issues the warning in the log and continues the execution of the pipeline.
@@ -163,42 +167,30 @@ If some problem that prevents success caching happens then the action issues the
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.17'
check-latest: true
cache-dependency-path: |
subdir/go.sum
tools/go.sum
# cache-dependency-path: "**/*.sum"
cache-dependency-path: subdir/go.sum
- run: go run hello.go
```
## Getting go version from the go.mod file
The `go-version-file` input accepts a path to a `go.mod` file or a `go.work`
file that contains the version of Go to be used by a project. The version taken
from thils file will be:
- The version from the `toolchain` directive, if there is one, otherwise
- The version from the `go` directive
The version can specify a patch version or omit it altogether (e.g., `go 1.22.0` or `go 1.22`).
If a patch version is specified, that specific patch version will be used.
If no patch version is specified, it will search for the latest available patch version in the cache,
[versions-manifest.json](https://github.com/actions/go-versions/blob/main/versions-manifest.json), and the
[official Go language website](https://golang.org/dl/?mode=json&include=all), in that order.
The `go-version-file` input accepts a path to a `go.mod` file or a `go.work` file that contains the version of Go to be
used by a project. As the `go.mod` file contains only major and minor (e.g. 1.18) tags, the action will search for the
latest available patch version sequentially in the runner's directory with the cached tools, in
the [versions-manifest.json](https://github.com/actions/go-versions/blob/main/versions-manifest.json) file or at the go
servers.
If both the `go-version` and the `go-version-file` inputs are provided then the `go-version` input is used.
> The action will search for the `go.mod` file relative to the repository root
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version-file: 'path/to/go.mod'
- run: go version
@@ -215,9 +207,9 @@ jobs:
go: [ '1.14', '1.13' ]
name: Go ${{ matrix.go }} sample
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v3
- name: Setup go
uses: actions/setup-go@v6
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go }}
- run: go run hello.go
@@ -235,35 +227,31 @@ documentation.
## Using `setup-go` on GHES
`setup-go` comes pre-installed on the appliance with GHES if Actions is enabled.
When dynamically downloading Go distributions, `setup-go` downloads distributions from [`actions/go-versions`](https://github.com/actions/go-versions) on github.com (outside of the appliance).
`setup-go` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Go
distributions, `setup-go` downloads distributions from [`actions/go-versions`](https://github.com/actions/go-versions)
on github.com (outside of the appliance). These calls to `actions/go-versions` are made via unauthenticated requests,
which are limited
to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). If
more requests are made within the time frame, then you will start to see rate-limit errors during downloading that looks
like: `##[error]API rate limit exceeded for...`. After that error the action will try to download versions directly
from https://storage.googleapis.com/golang, but it also can have rate limit so it's better to put token.
These calls to `actions/go-versions` are made via unauthenticated requests, which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting).
If more requests are made within the time frame, then the action leverages the `raw API` to retrieve the version-manifest. This approach does not impose a rate limit and hence facilitates unrestricted consumption. This is particularly beneficial for GHES runners, which often share the same IP, to avoid the quick exhaustion of the unauthenticated rate limit.
If that fails as well the action will try to download versions directly from https://storage.googleapis.com/golang.
If that fails as well you can get a higher rate limit with [generating a personal access token on github.com](https://github.com/settings/tokens/new) and passing it as the `token` input to the action:
To get a higher rate limit, you
can [generate a personal access token on github.com](https://github.com/settings/tokens/new) and pass it as the `token`
input for the action:
```yaml
uses: actions/setup-go@v6
uses: actions/setup-go@v4
with:
token: ${{ secrets.GH_DOTCOM_TOKEN }}
go-version: '1.18'
```
If the runner is not able to access github.com, any Go versions requested during a workflow run must come from the runner's tool cache.
If the runner is not able to access github.com, any Go versions requested during a workflow run must come from the
runner's tool cache.
See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server@3.2/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)"
for more information.
## Recommended permissions
When using the `setup-go` action in your GitHub Actions workflow, it is recommended to set the following permissions to ensure proper functionality:
```yaml
permissions:
contents: read # access to check out code and install dependencies
```
# License
The scripts and documentation in this project are released under the [MIT License](LICENSE)

View File

@@ -209,41 +209,3 @@ describe('isCacheFeatureAvailable', () => {
expect(warningSpy).toHaveBeenCalledWith(warningMessage);
});
});
describe('isGhes', () => {
const pristineEnv = process.env;
beforeEach(() => {
jest.resetModules();
process.env = {...pristineEnv};
});
afterAll(() => {
process.env = pristineEnv;
});
it('returns false when the GITHUB_SERVER_URL environment variable is not defined', async () => {
delete process.env['GITHUB_SERVER_URL'];
expect(cacheUtils.isGhes()).toBeFalsy();
});
it('returns false when the GITHUB_SERVER_URL environment variable is set to github.com', async () => {
process.env['GITHUB_SERVER_URL'] = 'https://github.com';
expect(cacheUtils.isGhes()).toBeFalsy();
});
it('returns false when the GITHUB_SERVER_URL environment variable is set to a GitHub Enterprise Cloud-style URL', async () => {
process.env['GITHUB_SERVER_URL'] = 'https://contoso.ghe.com';
expect(cacheUtils.isGhes()).toBeFalsy();
});
it('returns false when the GITHUB_SERVER_URL environment variable has a .localhost suffix', async () => {
process.env['GITHUB_SERVER_URL'] = 'https://mock-github.localhost';
expect(cacheUtils.isGhes()).toBeFalsy();
});
it('returns true when the GITHUB_SERVER_URL environment variable is set to some other URL', async () => {
process.env['GITHUB_SERVER_URL'] = 'https://src.onpremise.fabrikam.com';
expect(cacheUtils.isGhes()).toBeTruthy();
});
});

View File

@@ -1,6 +1,6 @@
module example.com/mymodule
go 1.20
go 1.14
require (
example.com/othermodule v1.2.3

View File

@@ -1,3 +1,3 @@
go 1.21
go 1.19
use .

View File

@@ -7,7 +7,6 @@ import osm, {type} from 'os';
import path from 'path';
import * as main from '../src/main';
import * as im from '../src/installer';
import * as httpm from '@actions/http-client';
import goJsonData from './data/golang-dl.json';
import matchers from '../matchers.json';
@@ -47,7 +46,6 @@ describe('setup-go', () => {
let execSpy: jest.SpyInstance;
let getManifestSpy: jest.SpyInstance;
let getAllVersionsSpy: jest.SpyInstance;
let httpmGetJsonSpy: jest.SpyInstance;
beforeAll(async () => {
process.env['GITHUB_ENV'] = ''; // Stub out Environment file functionality so we can verify it writes to standard out (toolkit is backwards compatible)
@@ -92,9 +90,6 @@ describe('setup-go', () => {
getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo');
getAllVersionsSpy = jest.spyOn(im, 'getManifest');
// httm
httpmGetJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson');
// io
whichSpy = jest.spyOn(io, 'which');
existsSpy = jest.spyOn(fs, 'existsSync');
@@ -129,9 +124,6 @@ describe('setup-go', () => {
});
afterEach(() => {
// clear out env var set during 'run'
delete process.env[im.GOTOOLCHAIN_ENV_VAR];
//jest.resetAllMocks();
jest.clearAllMocks();
//jest.restoreAllMocks();
@@ -159,21 +151,6 @@ describe('setup-go', () => {
);
});
it('should return manifest from repo', async () => {
const manifest = await im.getManifest(undefined);
expect(manifest).toEqual(goTestManifest);
});
it('should return manifest from raw URL if repo fetch fails', async () => {
getManifestSpy.mockRejectedValue(new Error('Fetch failed'));
httpmGetJsonSpy.mockResolvedValue({
result: goTestManifest
});
const manifest = await im.getManifest(undefined);
expect(httpmGetJsonSpy).toHaveBeenCalled();
expect(manifest).toEqual(goTestManifest);
});
it('can find 1.9 from manifest on linux', async () => {
os.platform = 'linux';
os.arch = 'x64';
@@ -288,7 +265,7 @@ describe('setup-go', () => {
expect(logSpy).toHaveBeenCalledWith(`Setup go version spec 1.13.0`);
});
it('does not export GOROOT for Go versions >=1.9', async () => {
it('does not export any variables for Go versions >=1.9', async () => {
inputs['go-version'] = '1.13.0';
inSpy.mockImplementation(name => inputs[name]);
@@ -301,7 +278,7 @@ describe('setup-go', () => {
});
await main.run();
expect(vars).not.toHaveProperty('GOROOT');
expect(vars).toStrictEqual({});
});
it('exports GOROOT for Go versions <1.9', async () => {
@@ -317,7 +294,9 @@ describe('setup-go', () => {
});
await main.run();
expect(vars).toHaveProperty('GOROOT', toolPath);
expect(vars).toStrictEqual({
GOROOT: toolPath
});
});
it('finds a version of go already in the cache', async () => {
@@ -811,9 +790,6 @@ describe('setup-go', () => {
getManifestSpy.mockImplementation(() => {
throw new Error('Unable to download manifest');
});
httpmGetJsonSpy.mockRejectedValue(
new Error('Unable to download manifest from raw URL')
);
getAllVersionsSpy.mockImplementationOnce(() => undefined);
dlSpy.mockImplementation(async () => '/some/temp/path');
@@ -990,104 +966,4 @@ use .
}
);
});
describe('go-version-file-toolchain', () => {
const goVersions = ['1.22.0', '1.21rc2', '1.18'];
const placeholderVersion = '1.19';
const buildGoMod = (
goVersion: string,
toolchainVersion: string
) => `module example.com/mymodule
go ${goVersion}
toolchain go${toolchainVersion}
require (
example.com/othermodule v1.2.3
example.com/thismodule v1.2.3
example.com/thatmodule v1.2.3
)
replace example.com/thatmodule => ../thatmodule
exclude example.com/thismodule v1.3.0
`;
const buildGoWork = (
goVersion: string,
toolchainVersion: string
) => `go 1.19
toolchain go${toolchainVersion}
use .
`;
goVersions.forEach(version => {
[
{
goVersionfile: 'go.mod',
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
expected_version: version,
desc: 'from toolchain directive'
},
{
goVersionfile: 'go.work',
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
expected_version: version,
desc: 'from toolchain directive'
},
{
goVersionfile: 'go.mod',
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
gotoolchain_env: 'local',
expected_version: placeholderVersion,
desc: 'from go directive when GOTOOLCHAIN is local'
},
{
goVersionfile: 'go.work',
fileContents: Buffer.from(buildGoMod(placeholderVersion, version)),
gotoolchain_env: 'local',
expected_version: placeholderVersion,
desc: 'from go directive when GOTOOLCHAIN is local'
}
].forEach(test => {
it(`reads version (${version}) in ${test.goVersionfile} ${test.desc}`, async () => {
inputs['go-version-file'] = test.goVersionfile;
if (test.gotoolchain_env !== undefined) {
process.env[im.GOTOOLCHAIN_ENV_VAR] = test.gotoolchain_env;
}
existsSpy.mockImplementation(() => true);
readFileSpy.mockImplementation(() => Buffer.from(test.fileContents));
await main.run();
expect(logSpy).toHaveBeenCalledWith(
`Setup go version spec ${test.expected_version}`
);
expect(logSpy).toHaveBeenCalledWith(
`Attempting to download ${test.expected_version}...`
);
expect(logSpy).toHaveBeenCalledWith(
`matching ${test.expected_version}...`
);
});
});
});
});
it('exports GOTOOLCHAIN and sets it in current process env', async () => {
inputs['go-version'] = '1.21.0';
inSpy.mockImplementation(name => inputs[name]);
const vars: {[key: string]: string} = {};
exportVarSpy.mockImplementation((name: string, val: string) => {
vars[name] = val;
});
await main.run();
expect(vars).toStrictEqual({GOTOOLCHAIN: 'local'});
expect(process.env).toHaveProperty('GOTOOLCHAIN', 'local');
});
});

View File

@@ -1,52 +0,0 @@
import {isSelfHosted} from '../src/utils';
describe('utils', () => {
describe('isSelfHosted', () => {
let AGENT_ISSELFHOSTED: string | undefined;
let RUNNER_ENVIRONMENT: string | undefined;
beforeEach(() => {
AGENT_ISSELFHOSTED = process.env['AGENT_ISSELFHOSTED'];
delete process.env['AGENT_ISSELFHOSTED'];
RUNNER_ENVIRONMENT = process.env['RUNNER_ENVIRONMENT'];
delete process.env['RUNNER_ENVIRONMENT'];
});
afterEach(() => {
if (AGENT_ISSELFHOSTED === undefined) {
delete process.env['AGENT_ISSELFHOSTED'];
} else {
process.env['AGENT_ISSELFHOSTED'] = AGENT_ISSELFHOSTED;
}
if (RUNNER_ENVIRONMENT === undefined) {
delete process.env['RUNNER_ENVIRONMENT'];
} else {
process.env['RUNNER_ENVIRONMENT'] = RUNNER_ENVIRONMENT;
}
});
it('isSelfHosted should be true if no environment variables set', () => {
expect(isSelfHosted()).toBeTruthy();
});
it('isSelfHosted should be true if environment variable is not set to denote GitHub hosted', () => {
process.env['RUNNER_ENVIRONMENT'] = 'some';
expect(isSelfHosted()).toBeTruthy();
});
it('isSelfHosted should be true if environment variable set to denote Azure Pipelines self hosted', () => {
process.env['AGENT_ISSELFHOSTED'] = '1';
expect(isSelfHosted()).toBeTruthy();
});
it('isSelfHosted should be false if environment variable set to denote GitHub hosted', () => {
process.env['RUNNER_ENVIRONMENT'] = 'github-hosted';
expect(isSelfHosted()).toBeFalsy();
});
it('isSelfHosted should be false if environment variable is not set to denote Azure Pipelines self hosted', () => {
process.env['AGENT_ISSELFHOSTED'] = 'some';
expect(isSelfHosted()).toBeFalsy();
});
});
});

View File

@@ -25,7 +25,7 @@ outputs:
cache-hit:
description: 'A boolean value to indicate if a cache was hit'
runs:
using: 'node20'
using: 'node16'
main: 'dist/setup/index.js'
post: 'dist/cache-save/index.js'
post-if: success()

13722
dist/cache-save/index.js vendored

File diff suppressed because it is too large Load Diff

18107
dist/setup/index.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -32,7 +32,7 @@ We don't pursue the goal to provide wide customization of caching in scope of `a
```yml
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '18'
@@ -43,7 +43,7 @@ steps:
```yml
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '18'
@@ -53,7 +53,7 @@ steps:
```yml
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '18'

9119
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,9 @@
{
"name": "setup-go",
"version": "6.0.0",
"version": "4.0.0",
"private": true,
"description": "setup go action",
"main": "lib/setup-go.js",
"engines": {
"node": ">=24.0.0"
},
"scripts": {
"build": "tsc && ncc build -o dist/setup src/setup-go.ts && ncc build -o dist/cache-save src/cache-save.ts",
"format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write \"**/*.{ts,yml,yaml}\"",
@@ -29,30 +26,30 @@
"license": "MIT",
"dependencies": {
"@actions/cache": "^4.0.3",
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/glob": "^0.5.0",
"@actions/http-client": "^2.2.1",
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.0",
"@actions/glob": "^0.2.0",
"@actions/http-client": "^2.0.1",
"@actions/io": "^1.0.2",
"@actions/tool-cache": "^2.0.2",
"semver": "^7.7.2"
"@actions/tool-cache": "^1.5.5",
"semver": "^6.3.1"
},
"devDependencies": {
"@types/jest": "^29.5.14",
"@types/node": "^24.1.0",
"@types/semver": "^7.7.1",
"@typescript-eslint/eslint-plugin": "^8.31.1",
"@typescript-eslint/parser": "^8.35.1",
"@vercel/ncc": "^0.38.1",
"eslint": "^8.57.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jest": "^29.0.1",
"@types/jest": "^27.0.2",
"@types/node": "^16.11.25",
"@types/semver": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
"@vercel/ncc": "^0.33.4",
"eslint": "^8.35.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-node": "^11.1.0",
"jest": "^29.7.0",
"jest-circus": "^29.7.0",
"jest": "^27.2.5",
"jest-circus": "^27.2.5",
"nock": "^10.0.6",
"prettier": "^2.8.4",
"ts-jest": "^29.3.2",
"typescript": "^5.8.3"
"ts-jest": "^27.0.5",
"typescript": "^4.3.3"
}
}

View File

@@ -15,7 +15,6 @@ export const restoreCache = async (
) => {
const packageManagerInfo = await getPackageManagerInfo(packageManager);
const platform = process.env.RUNNER_OS;
const arch = process.arch;
const cachePaths = await getCacheDirectoryPath(packageManagerInfo);
@@ -32,7 +31,7 @@ export const restoreCache = async (
const linuxVersion =
process.env.RUNNER_OS === 'Linux' ? `${process.env.ImageOS}-` : '';
const primaryKey = `setup-go-${platform}-${arch}-${linuxVersion}go-${versionSpec}-${fileHash}`;
const primaryKey = `setup-go-${platform}-${linuxVersion}go-${versionSpec}-${fileHash}`;
core.debug(`primary key is ${primaryKey}`);
core.saveState(State.CachePrimaryKey, primaryKey);

View File

@@ -12,19 +12,9 @@ process.on('uncaughtException', e => {
core.info(`${warningPrefix}${e.message}`);
});
// Added early exit to resolve issue with slow post action step:
// - https://github.com/actions/setup-node/issues/878
// https://github.com/actions/cache/pull/1217
export async function run(earlyExit?: boolean) {
export async function run() {
try {
const cacheInput = core.getBooleanInput('cache');
if (cacheInput) {
await cachePackages();
if (earlyExit) {
process.exit(0);
}
}
} catch (error) {
let message = 'Unknown error!';
if (error instanceof Error) {
@@ -38,6 +28,11 @@ export async function run(earlyExit?: boolean) {
}
const cachePackages = async () => {
const cacheInput = core.getBooleanInput('cache');
if (!cacheInput) {
return;
}
const packageManager = 'default';
const state = core.getState(State.CacheMatchedKey);
@@ -90,4 +85,4 @@ function logWarning(message: string): void {
core.info(`${warningPrefix}${message}`);
}
run(true);
run();

View File

@@ -63,13 +63,7 @@ export function isGhes(): boolean {
const ghUrl = new URL(
process.env['GITHUB_SERVER_URL'] || 'https://github.com'
);
const hostname = ghUrl.hostname.trimEnd().toUpperCase();
const isGitHubHost = hostname === 'GITHUB.COM';
const isGitHubEnterpriseCloudHost = hostname.endsWith('.GHE.COM');
const isLocalHost = hostname.endsWith('.LOCALHOST');
return !isGitHubHost && !isGitHubEnterpriseCloudHost && !isLocalHost;
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
}
export function isCacheFeatureAvailable(): boolean {

View File

@@ -6,15 +6,7 @@ import * as httpm from '@actions/http-client';
import * as sys from './system';
import fs from 'fs';
import os from 'os';
import {StableReleaseAlias, isSelfHosted} from './utils';
import {Architecture} from './types';
export const GOTOOLCHAIN_ENV_VAR = 'GOTOOLCHAIN';
export const GOTOOLCHAIN_LOCAL_VAL = 'local';
const MANIFEST_REPO_OWNER = 'actions';
const MANIFEST_REPO_NAME = 'go-versions';
const MANIFEST_REPO_BRANCH = 'main';
const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`;
import {StableReleaseAlias} from './utils';
type InstallationType = 'dist' | 'manifest';
@@ -42,7 +34,7 @@ export async function getGo(
versionSpec: string,
checkLatest: boolean,
auth: string | undefined,
arch: Architecture = os.arch() as Architecture
arch = os.arch()
) {
let manifest: tc.IToolRelease[] | undefined;
const osPlat: string = os.platform();
@@ -122,9 +114,9 @@ export async function getGo(
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
);
} else {
core.info((err as Error).message);
core.info(err.message);
}
core.debug((err as Error).stack ?? '');
core.debug(err.stack);
core.info('Falling back to download directly from Go');
}
@@ -154,7 +146,7 @@ async function resolveVersionFromManifest(
versionSpec: string,
stable: boolean,
auth: string | undefined,
arch: Architecture,
arch: string,
manifest: tc.IToolRelease[] | undefined
): Promise<string | undefined> {
try {
@@ -168,7 +160,7 @@ async function resolveVersionFromManifest(
return info?.resolvedVersion;
} catch (err) {
core.info('Unable to resolve a version from the manifest...');
core.debug((err as Error).message);
core.debug(err.message);
}
}
@@ -183,7 +175,11 @@ async function cacheWindowsDir(
if (os.platform() !== 'win32') return false;
// make sure the action runs in the hosted environment
if (isSelfHosted()) return false;
if (
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' &&
process.env['AGENT_ISSELFHOSTED'] === '1'
)
return false;
const defaultToolCacheRoot = process.env['RUNNER_TOOL_CACHE'];
if (!defaultToolCacheRoot) return false;
@@ -207,17 +203,6 @@ async function cacheWindowsDir(
fs.symlinkSync(actualToolCacheDir, defaultToolCacheDir, 'junction');
core.info(`Created link ${defaultToolCacheDir} => ${actualToolCacheDir}`);
const actualToolCacheCompleteFile = `${actualToolCacheDir}.complete`;
const defaultToolCacheCompleteFile = `${defaultToolCacheDir}.complete`;
fs.symlinkSync(
actualToolCacheCompleteFile,
defaultToolCacheCompleteFile,
'file'
);
core.info(
`Created link ${defaultToolCacheCompleteFile} => ${actualToolCacheCompleteFile}`
);
// make outer code to continue using toolcache as if it were installed on c:
// restore toolcache root to default drive c:
process.env['RUNNER_TOOL_CACHE'] = defaultToolCacheRoot;
@@ -278,85 +263,15 @@ export async function extractGoArchive(archivePath: string): Promise<string> {
return extPath;
}
function isIToolRelease(obj: any): obj is tc.IToolRelease {
return (
typeof obj === 'object' &&
obj !== null &&
typeof obj.version === 'string' &&
typeof obj.stable === 'boolean' &&
Array.isArray(obj.files) &&
obj.files.every(
(file: any) =>
typeof file.filename === 'string' &&
typeof file.platform === 'string' &&
typeof file.arch === 'string' &&
typeof file.download_url === 'string'
)
);
}
export async function getManifest(
auth: string | undefined
): Promise<tc.IToolRelease[]> {
try {
const manifest = await getManifestFromRepo(auth);
if (
Array.isArray(manifest) &&
manifest.length &&
manifest.every(isIToolRelease)
) {
return manifest;
}
let errorMessage =
'An unexpected error occurred while fetching the manifest.';
if (
typeof manifest === 'object' &&
manifest !== null &&
'message' in manifest
) {
errorMessage = (manifest as {message: string}).message;
}
throw new Error(errorMessage);
} catch (err) {
core.debug('Fetching the manifest via the API failed.');
if (err instanceof Error) {
core.debug(err.message);
}
}
return await getManifestFromURL();
}
function getManifestFromRepo(
auth: string | undefined
): Promise<tc.IToolRelease[]> {
core.debug(
`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`
);
return tc.getManifestFromRepo(
MANIFEST_REPO_OWNER,
MANIFEST_REPO_NAME,
auth,
MANIFEST_REPO_BRANCH
);
}
async function getManifestFromURL(): Promise<tc.IToolRelease[]> {
core.debug('Falling back to fetching the manifest using raw URL.');
const http: httpm.HttpClient = new httpm.HttpClient('tool-cache');
const response = await http.getJson<tc.IToolRelease[]>(MANIFEST_URL);
if (!response.result) {
throw new Error(`Unable to get manifest from ${MANIFEST_URL}`);
}
return response.result;
export async function getManifest(auth: string | undefined) {
return tc.getManifestFromRepo('actions', 'go-versions', auth, 'main');
}
export async function getInfoFromManifest(
versionSpec: string,
stable: boolean,
auth: string | undefined,
arch: Architecture = os.arch() as Architecture,
arch = os.arch(),
manifest?: tc.IToolRelease[] | undefined
): Promise<IGoVersionInfo | null> {
let info: IGoVersionInfo | null = null;
@@ -382,7 +297,7 @@ export async function getInfoFromManifest(
async function getInfoFromDist(
versionSpec: string,
arch: Architecture
arch: string
): Promise<IGoVersionInfo | null> {
const version: IGoVersion | undefined = await findMatch(versionSpec, arch);
if (!version) {
@@ -401,7 +316,7 @@ async function getInfoFromDist(
export async function findMatch(
versionSpec: string,
arch: Architecture = os.arch() as Architecture
arch = os.arch()
): Promise<IGoVersion | undefined> {
const archFilter = sys.getArch(arch);
const platFilter = sys.getPlatform();
@@ -498,30 +413,14 @@ export function parseGoVersionFile(versionFilePath: string): string {
path.basename(versionFilePath) === 'go.mod' ||
path.basename(versionFilePath) === 'go.work'
) {
// for backwards compatibility: use version from go directive if
// 'GOTOOLCHAIN' has been explicitly set
if (process.env[GOTOOLCHAIN_ENV_VAR] !== GOTOOLCHAIN_LOCAL_VAL) {
// toolchain directive: https://go.dev/ref/mod#go-mod-file-toolchain
const matchToolchain = contents.match(
/^toolchain go(1\.\d+(?:\.\d+|rc\d+)?)/m
);
if (matchToolchain) {
return matchToolchain[1];
}
}
// go directive: https://go.dev/ref/mod#go-mod-file-go
const matchGo = contents.match(/^go (\d+(\.\d+)*)/m);
return matchGo ? matchGo[1] : '';
const match = contents.match(/^go (\d+(\.\d+)*)/m);
return match ? match[1] : '';
}
return contents.trim();
}
async function resolveStableVersionDist(
versionSpec: string,
arch: Architecture
) {
async function resolveStableVersionDist(versionSpec: string, arch: string) {
const archFilter = sys.getArch(arch);
const platFilter = sys.getPlatform();
const dlUrl = 'https://golang.org/dl/?mode=json&include=all';

View File

@@ -8,7 +8,6 @@ import {isCacheFeatureAvailable} from './cache-utils';
import cp from 'child_process';
import fs from 'fs';
import os from 'os';
import {Architecture} from './types';
export async function run() {
try {
@@ -17,15 +16,14 @@ export async function run() {
// If not supplied then problem matchers will still be setup. Useful for self-hosted.
//
const versionSpec = resolveVersionInput();
setGoToolchain();
const cache = core.getBooleanInput('cache');
core.info(`Setup go version spec ${versionSpec}`);
let arch = core.getInput('architecture') as Architecture;
let arch = core.getInput('architecture');
if (!arch) {
arch = os.arch() as Architecture;
arch = os.arch();
}
if (versionSpec) {
@@ -76,7 +74,7 @@ export async function run() {
cacheDependencyPath
);
} catch (error) {
core.warning(`Restore cache failed: ${(error as Error).message}`);
core.warning(`Restore cache failed: ${error.message}`);
}
}
@@ -94,7 +92,7 @@ export async function run() {
core.info(goEnv);
core.endGroup();
} catch (error) {
core.setFailed((error as Error).message);
core.setFailed(error.message);
}
}
@@ -162,20 +160,3 @@ function resolveVersionInput(): string {
return version;
}
function setGoToolchain() {
// docs: https://go.dev/doc/toolchain
// "local indicates the bundled Go toolchain (the one that shipped with the go command being run)"
// this is so any 'go' command is run with the selected Go version
// and doesn't trigger a toolchain download and run commands with that
// see e.g. issue #424
// and a similar discussion: https://github.com/docker-library/golang/issues/472.
// Set the value in process env so any `go` commands run as child-process
// don't cause toolchain downloads
process.env[installer.GOTOOLCHAIN_ENV_VAR] = installer.GOTOOLCHAIN_LOCAL_VAL;
// and in the runner env so e.g. a user running `go mod tidy` won't cause it
core.exportVariable(
installer.GOTOOLCHAIN_ENV_VAR,
installer.GOTOOLCHAIN_LOCAL_VAL
);
}

View File

@@ -1,5 +1,4 @@
import os from 'os';
import {Architecture} from './types';
export function getPlatform(): string {
// darwin and linux match already
@@ -16,7 +15,7 @@ export function getPlatform(): string {
return plat;
}
export function getArch(arch: Architecture): string {
export function getArch(arch: string): string {
// 'arm', 'arm64', 'ia32', 'mips', 'mipsel', 'ppc', 'ppc64', 's390', 's390x', 'x32', and 'x64'.
// wants amd64, 386, arm64, armv61, ppc641e, s390x

View File

@@ -1,2 +0,0 @@
// match what @actions/tool-cache expects
export type Architecture = string;

View File

@@ -2,13 +2,3 @@ export enum StableReleaseAlias {
Stable = 'stable',
OldStable = 'oldstable'
}
export const isSelfHosted = (): boolean =>
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' &&
(process.env['AGENT_ISSELFHOSTED'] === '1' ||
process.env['AGENT_ISSELFHOSTED'] === undefined);
/* the above is simplified from:
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' && process.env['AGENT_ISSELFHOSTED'] === '1'
||
process.env['RUNNER_ENVIRONMENT'] !== 'github-hosted' && process.env['AGENT_ISSELFHOSTED'] === undefined
*/