Compare commits

..

No commits in common. "master" and "v7.1.0" have entirely different histories.

15 changed files with 127 additions and 358 deletions

View file

@ -37,21 +37,25 @@ jobs:
- goreleaser - goreleaser
- goreleaser-pro - goreleaser-pro
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Go -
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with: with:
go-version: stable go-version: stable
- name: Check -
name: Check
uses: ./ uses: ./
with: with:
version: ${{ matrix.version }} version: ${{ matrix.version }}
args: check --verbose args: check --verbose
workdir: ./test workdir: ./test
- name: GoReleaser -
name: GoReleaser
if: ${{ !(github.event_name == 'pull_request' && matrix.distribution == 'goreleaser-pro') }} if: ${{ !(github.event_name == 'pull_request' && matrix.distribution == 'goreleaser-pro') }}
uses: ./ uses: ./
env: env:
@ -77,25 +81,30 @@ jobs:
- true - true
- false - false
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Go -
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with: with:
go-version: 1.18 go-version: 1.18
- name: Install cosign -
name: Install cosign
if: matrix.cosign if: matrix.cosign
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
- name: GoReleaser -
name: GoReleaser
if: ${{ !(github.event_name == 'pull_request' && matrix.distribution == 'goreleaser-pro') }} if: ${{ !(github.event_name == 'pull_request' && matrix.distribution == 'goreleaser-pro') }}
uses: ./ uses: ./
with: with:
distribution: ${{ matrix.distribution }} distribution: ${{ matrix.distribution }}
version: ${{ matrix.version }} version: ${{ matrix.version }}
install-only: true install-only: true
- name: Check -
name: Check
if: ${{ !(github.event_name == 'pull_request' && matrix.distribution == 'goreleaser-pro') }} if: ${{ !(github.event_name == 'pull_request' && matrix.distribution == 'goreleaser-pro') }}
run: | run: |
goreleaser check --verbose goreleaser check --verbose
@ -111,21 +120,25 @@ jobs:
- macos-latest - macos-latest
- windows-latest - windows-latest
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Go -
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with: with:
go-version: 1.18 go-version: 1.18
- name: Import GPG key -
name: Import GPG key
id: import_gpg id: import_gpg
uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd # v7.0.0 uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd # v7.0.0
with: with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY_TEST }} gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY_TEST }}
passphrase: ${{ secrets.PASSPHRASE_TEST }} passphrase: ${{ secrets.PASSPHRASE_TEST }}
- name: Check -
name: Check
uses: ./ uses: ./
with: with:
version: latest version: latest
@ -133,7 +146,8 @@ jobs:
workdir: ./test workdir: ./test
env: env:
GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
- name: GoReleaser -
name: GoReleaser
uses: ./ uses: ./
with: with:
version: latest version: latest
@ -145,26 +159,31 @@ jobs:
upload-artifact: upload-artifact:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Go -
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with: with:
go-version: 1.18 go-version: 1.18
- name: Check -
name: Check
uses: ./ uses: ./
with: with:
args: check --verbose args: check --verbose
workdir: ./test workdir: ./test
- name: GoReleaser -
name: GoReleaser
uses: ./ uses: ./
with: with:
args: release --skip=publish --clean --snapshot args: release --skip=publish --clean --snapshot
workdir: ./test workdir: ./test
- name: Upload assets -
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 name: Upload assets
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: myapp name: myapp
path: ./test/dist/* path: ./test/dist/*
@ -172,20 +191,24 @@ jobs:
dist: dist:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Go -
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with: with:
go-version: 1.18 go-version: 1.18
- name: GoReleaser -
name: GoReleaser
uses: ./ uses: ./
with: with:
args: release --config .goreleaser-dist.yml --skip=publish --clean --snapshot args: release --config .goreleaser-dist.yml --skip=publish --clean --snapshot
workdir: ./test workdir: ./test
- name: Check dist -
name: Check dist
run: | run: |
tree -nh ./test/_output tree -nh ./test/_output
@ -202,24 +225,27 @@ jobs:
- goreleaser-pro - goreleaser-pro
- goreleaser - goreleaser
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Go -
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with: with:
go-version: 1.18 go-version: 1.18
- name: GoReleaser -
name: GoReleaser
uses: ./ uses: ./
with: with:
install-only: true install-only: true
distribution: ${{ matrix.distribution }} distribution: ${{ matrix.distribution }}
version: nightly version: nightly
env: -
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} name: Check
- name: Check
run: | run: |
goreleaser check -f ./test/.goreleaser.yml goreleaser check -f ./test/.goreleaser.yml
goreleaser --version goreleaser --version
goreleaser --version | grep nightly goreleaser --version | grep nightly

View file

@ -28,15 +28,19 @@ jobs:
tag: tag:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Git config -
name: Git config
run: | run: |
git config user.name "github-actions[bot]" git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Move ${{ github.event.inputs.major_version }} to ${{ github.event.inputs.target }} -
name: Move ${{ github.event.inputs.major_version }} to ${{ github.event.inputs.target }}
run: git tag -f ${{ github.event.inputs.major_version }} ${{ github.event.inputs.target }} run: git tag -f ${{ github.event.inputs.major_version }} ${{ github.event.inputs.target }}
- name: Push -
name: Push
run: git push origin ${{ github.event.inputs.major_version }} --force run: git push origin ${{ github.event.inputs.major_version }} --force

View file

@ -19,24 +19,28 @@ jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Node.js -
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v6.0.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: npm cache: npm
- name: Install cosign -
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 name: Install cosign
- name: Install dependencies uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
-
name: Install dependencies
run: npm ci run: npm ci
- name: Test -
name: Test
run: npm test run: npm test
env: -
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} name: Upload coverage
- name: Upload coverage
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
with: with:
files: ./coverage/clover.xml files: ./coverage/clover.xml

View file

@ -19,35 +19,45 @@ jobs:
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node.js -
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v6.0.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: npm cache: npm
- name: Install dependencies -
name: Install dependencies
run: npm ci run: npm ci
- name: Format check -
name: Format check
run: npm run format-check run: npm run format-check
- name: Lint -
name: Lint
run: npm run lint run: npm run lint
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node.js -
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0 name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v6.0.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: npm cache: npm
- name: Install dependencies -
name: Install dependencies
run: npm ci --ignore-scripts run: npm ci --ignore-scripts
- name: Rebuild dist -
name: Rebuild dist
run: npm run build run: npm run build
- name: Compare dist -
name: Compare dist
id: diff id: diff
run: | run: |
if [ "$(git diff --ignore-space-at-eol dist | wc -l)" -gt "0" ]; then if [ "$(git diff --ignore-space-at-eol dist | wc -l)" -gt "0" ]; then
@ -55,9 +65,10 @@ jobs:
git diff dist git diff dist
exit 1 exit 1
fi fi
- name: Upload built dist on failure -
name: Upload built dist on failure
if: ${{ failure() && steps.diff.conclusion == 'failure' }} if: ${{ failure() && steps.diff.conclusion == 'failure' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: dist name: dist
path: dist path: dist
@ -65,16 +76,20 @@ jobs:
vendor: vendor:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout -
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Node.js -
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0 name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v6.0.0
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: npm cache: npm
- name: Refresh package-lock.json -
name: Refresh package-lock.json
run: npm install --package-lock-only run: npm install --package-lock-only
- name: Compare package-lock.json -
name: Compare package-lock.json
run: | run: |
if [ -n "$(git status --porcelain -- package-lock.json)" ]; then if [ -n "$(git status --porcelain -- package-lock.json)" ]; then
echo "package-lock.json is out of sync with package.json. Run 'npm install' and commit." >&2 echo "package-lock.json is out of sync with package.json. Run 'npm install' and commit." >&2

View file

@ -96,11 +96,6 @@ checksums file against the GoReleaser release workflow's OIDC identity. If
> versions the cosign step is silently skipped — only the `checksums.txt` > versions the cosign step is silently skipped — only the `checksums.txt`
> SHA-256 verification runs. > SHA-256 verification runs.
> **Note**: when `version: nightly` is used, the action resolves the
> latest immutable `vX.Y.Z-<sha>-nightly` release from the GitHub
> Releases API. Pass `GITHUB_TOKEN` to the action step (as in the example
> above) to avoid unauthenticated API rate limits.
To enable signature verification, install cosign before running the action: To enable signature verification, install cosign before running the action:
```yaml ```yaml
@ -227,28 +222,11 @@ Following inputs can be used as `step.with` keys
|------------------|---------|--------------|------------------------------------------------------------------| |------------------|---------|--------------|------------------------------------------------------------------|
| `distribution` | String | `goreleaser` | GoReleaser distribution, either `goreleaser` or `goreleaser-pro` | | `distribution` | String | `goreleaser` | GoReleaser distribution, either `goreleaser` or `goreleaser-pro` |
| `version`**Âą** | String | `~> v2` | GoReleaser version | | `version`**Âą** | String | `~> v2` | GoReleaser version |
| `version-file`**²** | String | | Read the GoReleaser version from a file (see below) |
| `args` | String | | Arguments to pass to GoReleaser | | `args` | String | | Arguments to pass to GoReleaser |
| `workdir` | String | `.` | Working directory (below repository root) | | `workdir` | String | `.` | Working directory (below repository root) |
| `install-only` | Bool | `false` | Just install GoReleaser | | `install-only` | Bool | `false` | Just install GoReleaser |
> **Âą** Can be a fixed version like `v0.117.0` or a max satisfying semver one like `~> 0.132`. In this case this will return `v0.132.1`. > **Âą** Can be a fixed version like `v0.117.0` or a max satisfying semver one like `~> 0.132`. In this case this will return `v0.132.1`.
>
> **²** Path to a file containing the GoReleaser version. Resolved relative
> to `workdir`. Currently only [`.tool-versions`](https://asdf-vm.com/manage/configuration.html#tool-versions)
> (asdf/mise) format is supported. When set, this takes precedence over `version`.
>
> ```yaml
> # .tool-versions
> goreleaser 2.13.0
> ```
>
> ```yaml
> - uses: goreleaser/goreleaser-action@v7
> with:
> version-file: .tool-versions
> args: release --clean
> ```
### outputs ### outputs

View file

@ -56,16 +56,16 @@ describe('getRelease', () => {
expect(release?.tag_name).not.toEqual(''); expect(release?.tag_name).not.toEqual('');
}); });
it('resolves nightly to a <version>-<sha>-nightly release for OSS GoReleaser', async () => { it('returns nightly GoReleaser GitHub release', async () => {
const release = await github.getRelease('goreleaser', 'nightly'); const release = await github.getRelease('goreleaser', 'nightly');
expect(release).not.toBeNull(); expect(release).not.toBeNull();
expect(release.tag_name).toMatch(github.nightlyTagRegex); expect(release?.tag_name).not.toEqual('');
}); });
it('resolves nightly to a <version>-<sha>-nightly release for GoReleaser Pro', async () => { it('returns nightly GoReleaser Pro GitHub release', async () => {
const release = await github.getRelease('goreleaser-pro', 'nightly'); const release = await github.getRelease('goreleaser-pro', 'nightly');
expect(release).not.toBeNull(); expect(release).not.toBeNull();
expect(release.tag_name).toMatch(github.nightlyTagRegex); expect(release?.tag_name).not.toEqual('');
}); });
it('returns v0.182.0 GoReleaser Pro GitHub release', async () => { it('returns v0.182.0 GoReleaser Pro GitHub release', async () => {

View file

@ -16,38 +16,11 @@ describe('install', () => {
expect(fs.existsSync(bin)).toBe(true); expect(fs.existsSync(bin)).toBe(true);
}, 100000); }, 100000);
// The following pinned versions exercise install across release eras to
// guard against regressions in checksum handling and the cosign skip path:
// - v0.182.0 : pre-checksums-signing era
// - v1.26.2 : cosign v2 detached `.sig` only
// - v2.12.4 : last release before sigstore bundles (cosign skipped)
// - v2.13.0 : first release with cosign v3 sigstore bundle
// - v2.15.3 : recent release with sigstore bundle
it('acquires v0.182.0 (pre-signing) version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', 'v0.182.0');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
it('acquires v1.26.2 (cosign v2 .sig) version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', 'v1.26.2');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
it('acquires v2.12.4 (last pre-sigstore-bundle) version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', 'v2.12.4');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
it('acquires v2.13.0 (minimum cosign-verifiable) version of GoReleaser', async () => { it('acquires v2.13.0 (minimum cosign-verifiable) version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', 'v2.13.0'); const bin = await goreleaser.install('goreleaser', 'v2.13.0');
expect(fs.existsSync(bin)).toBe(true); expect(fs.existsSync(bin)).toBe(true);
}, 100000); }, 100000);
it('acquires v2.15.3 (recent sigstore-bundle) version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', 'v2.15.3');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
it('acquires latest v2 version of GoReleaser Pro', async () => { it('acquires latest v2 version of GoReleaser Pro', async () => {
const bin = await goreleaser.install('goreleaser-pro', '~> v2'); const bin = await goreleaser.install('goreleaser-pro', '~> v2');
expect(fs.existsSync(bin)).toBe(true); expect(fs.existsSync(bin)).toBe(true);
@ -104,14 +77,14 @@ describe('getCertificateIdentity', () => {
); );
}); });
it('uses nightly-oss.yml@refs/heads/main for OSS nightly tag', () => { it('uses nightly-oss.yml@refs/heads/main for OSS nightly', () => {
expect(goreleaser.getCertificateIdentity('goreleaser', 'v2.16.0-abc1234-nightly')).toEqual( expect(goreleaser.getCertificateIdentity('goreleaser', 'nightly')).toEqual(
'https://github.com/goreleaser/goreleaser/.github/workflows/nightly-oss.yml@refs/heads/main' 'https://github.com/goreleaser/goreleaser/.github/workflows/nightly-oss.yml@refs/heads/main'
); );
}); });
it('uses nightly-pro.yml@refs/heads/main for Pro nightly tag', () => { it('uses nightly-pro.yml@refs/heads/main for Pro nightly', () => {
expect(goreleaser.getCertificateIdentity('goreleaser-pro', 'v2.16.0-eaeb08c50-nightly')).toEqual( expect(goreleaser.getCertificateIdentity('goreleaser-pro', 'nightly')).toEqual(
'https://github.com/goreleaser/goreleaser-pro-internal/.github/workflows/nightly-pro.yml@refs/heads/main' 'https://github.com/goreleaser/goreleaser-pro-internal/.github/workflows/nightly-pro.yml@refs/heads/main'
); );
}); });
@ -139,14 +112,6 @@ describe('verifyChecksum', () => {
expect(fs.existsSync(bin)).toBe(true); expect(fs.existsSync(bin)).toBe(true);
}, 120000); }, 120000);
it('installs a pre-v2.13 release (no sigstore bundle) without failing when cosign is present', async () => {
// v2.12.x is the last release that did NOT publish checksums.txt.sigstore.json.
// The action must still install it cleanly: checksum verified, cosign step skipped.
await requireCosign();
const bin = await goreleaser.install('goreleaser', 'v2.12.4');
expect(fs.existsSync(bin)).toBe(true);
}, 120000);
it('throws on checksum mismatch', async () => { it('throws on checksum mismatch', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gha-')); const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gha-'));
const archive = path.join(dir, 'fake.tar.gz'); const archive = path.join(dir, 'fake.tar.gz');

View file

@ -1,117 +0,0 @@
import {describe, expect, it, beforeEach, afterEach} from '@jest/globals';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import {getRequestedVersion} from '../src/version';
import {Inputs} from '../src/context';
const baseInputs = (overrides: Partial<Inputs>): Inputs => ({
distribution: 'goreleaser',
version: '~> v2',
versionFile: '',
args: '',
workdir: '.',
installOnly: false,
...overrides
});
describe('getRequestedVersion', () => {
let tmpDir: string;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'goreleaser-version-'));
});
afterEach(() => {
fs.rmSync(tmpDir, {recursive: true, force: true});
});
const writeToolVersions = (content: string, name = '.tool-versions'): void => {
fs.writeFileSync(path.join(tmpDir, name), content);
};
describe('without version-file', () => {
it('returns the version input as-is', () => {
expect(getRequestedVersion(baseInputs({version: 'v1.2.3'}))).toBe('v1.2.3');
});
it('returns the default version when none is provided', () => {
expect(getRequestedVersion(baseInputs({version: '~> v2'}))).toBe('~> v2');
});
});
describe('with .tool-versions', () => {
it('parses an unprefixed version and adds the v prefix', () => {
writeToolVersions('goreleaser 1.2.3\n');
expect(getRequestedVersion(baseInputs({versionFile: '.tool-versions', workdir: tmpDir}))).toBe('v1.2.3');
});
it('keeps an existing v prefix without doubling it', () => {
writeToolVersions('goreleaser v1.2.3\n');
expect(getRequestedVersion(baseInputs({versionFile: '.tool-versions', workdir: tmpDir}))).toBe('v1.2.3');
});
it('takes precedence over the version input', () => {
writeToolVersions('goreleaser 1.2.3\n');
expect(getRequestedVersion(baseInputs({version: 'v9.9.9', versionFile: '.tool-versions', workdir: tmpDir}))).toBe(
'v1.2.3'
);
});
it('ignores other tools and picks goreleaser', () => {
writeToolVersions(['nodejs 20.10.0', 'goreleaser 2.13.0', 'python 3.12.1', ''].join('\n'));
expect(getRequestedVersion(baseInputs({versionFile: '.tool-versions', workdir: tmpDir}))).toBe('v2.13.0');
});
it('skips full-line and inline comments', () => {
writeToolVersions(['# pinned for CI', 'goreleaser 2.13.0 # minimum cosign-verifiable', ''].join('\n'));
expect(getRequestedVersion(baseInputs({versionFile: '.tool-versions', workdir: tmpDir}))).toBe('v2.13.0');
});
it('preserves "latest"', () => {
writeToolVersions('goreleaser latest\n');
expect(getRequestedVersion(baseInputs({versionFile: '.tool-versions', workdir: tmpDir}))).toBe('latest');
});
it('uses only the first version when multiple fallbacks are listed', () => {
// asdf supports listing fallback versions; we install the first match.
writeToolVersions('goreleaser 2.13.0 2.12.4\n');
expect(getRequestedVersion(baseInputs({versionFile: '.tool-versions', workdir: tmpDir}))).toBe('v2.13.0');
});
it('accepts an absolute path and ignores workdir', () => {
const abs = path.join(tmpDir, '.tool-versions');
fs.writeFileSync(abs, 'goreleaser 2.13.0\n');
expect(getRequestedVersion(baseInputs({versionFile: abs, workdir: '/nonexistent'}))).toBe('v2.13.0');
});
it('throws when the file does not exist', () => {
expect(() => getRequestedVersion(baseInputs({versionFile: '.tool-versions', workdir: tmpDir}))).toThrow(
/version-file not found/
);
});
it('throws when the file has no goreleaser entry', () => {
writeToolVersions(['nodejs 20.10.0', 'python 3.12.1', ''].join('\n'));
expect(() => getRequestedVersion(baseInputs({versionFile: '.tool-versions', workdir: tmpDir}))).toThrow(
/No goreleaser entry/
);
});
it('throws when the goreleaser entry has no version', () => {
writeToolVersions('goreleaser\n');
expect(() => getRequestedVersion(baseInputs({versionFile: '.tool-versions', workdir: tmpDir}))).toThrow(
/No version specified for goreleaser/
);
});
});
describe('with an unsupported file', () => {
it('throws a clear error', () => {
fs.writeFileSync(path.join(tmpDir, '.go-version'), '1.2.3\n');
expect(() => getRequestedVersion(baseInputs({versionFile: '.go-version', workdir: tmpDir}))).toThrow(
/Unsupported version-file/
);
});
});
});

View file

@ -15,12 +15,6 @@ inputs:
description: 'GoReleaser version' description: 'GoReleaser version'
default: '~> v2' default: '~> v2'
required: false required: false
version-file:
description: |
Read the GoReleaser version from a file. Path is resolved relative to
`workdir`. Currently only `.tool-versions` (asdf/mise) is supported.
When set, takes precedence over `version`.
required: false
args: args:
description: 'Arguments to pass to GoReleaser' description: 'Arguments to pass to GoReleaser'
required: false required: false

4
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

View file

@ -7,7 +7,6 @@ export const osArch: string = os.arch();
export interface Inputs { export interface Inputs {
distribution: string; distribution: string;
version: string; version: string;
versionFile: string;
args: string; args: string;
workdir: string; workdir: string;
installOnly: boolean; installOnly: boolean;
@ -17,7 +16,6 @@ export async function getInputs(): Promise<Inputs> {
return { return {
distribution: core.getInput('distribution') || 'goreleaser', distribution: core.getInput('distribution') || 'goreleaser',
version: core.getInput('version') || '~> v2', version: core.getInput('version') || '~> v2',
versionFile: core.getInput('version-file'),
args: core.getInput('args'), args: core.getInput('args'),
workdir: core.getInput('workdir') || '.', workdir: core.getInput('workdir') || '.',
installOnly: core.getBooleanInput('install-only') installOnly: core.getBooleanInput('install-only')

View file

@ -30,13 +30,6 @@ export interface GitHubRelease {
tag_name: string; tag_name: string;
} }
// Matches the new-style nightly release tag pattern: vX.Y.Z-<sha>-nightly
export const nightlyTagRegex = /^v\d+\.\d+\.\d+-[0-9a-f]+-nightly$/i;
export const isNightlyTag = (tag: string): boolean => {
return nightlyTagRegex.test(tag);
};
export const getRelease = async (distribution: string, version: string): Promise<GitHubRelease> => { export const getRelease = async (distribution: string, version: string): Promise<GitHubRelease> => {
if (version === 'latest') { if (version === 'latest') {
core.warning("You are using 'latest' as default version. Will lock to '~> v2'."); core.warning("You are using 'latest' as default version. Will lock to '~> v2'.");
@ -47,7 +40,7 @@ export const getRelease = async (distribution: string, version: string): Promise
export const getReleaseTag = async (distribution: string, version: string): Promise<GitHubRelease> => { export const getReleaseTag = async (distribution: string, version: string): Promise<GitHubRelease> => {
if (version === 'nightly') { if (version === 'nightly') {
return resolveNightly(distribution); return {tag_name: version};
} }
// If version is a specific version (not a range), skip the JSON check // If version is a specific version (not a range), skip the JSON check
@ -88,39 +81,6 @@ export const getReleaseTag = async (distribution: string, version: string): Prom
throw new Error(`Cannot find GoReleaser release ${version} in ${url}`); throw new Error(`Cannot find GoReleaser release ${version} in ${url}`);
}; };
// resolveNightly looks up the latest immutable nightly release of the form
// `vX.Y.Z-<sha>-nightly` on the GitHub releases of the given distribution.
const resolveNightly = async (distribution: string): Promise<GitHubRelease> => {
const url = `https://api.github.com/repos/goreleaser/${distribution}/releases?per_page=100`;
core.debug(`Resolving latest nightly release from ${url}`);
const releases = await withRetry(async () => {
const http: httpm.HttpClient = new httpm.HttpClient('goreleaser-action');
const headers: {[name: string]: string} = {
Accept: 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28'
};
const token = process.env.GITHUB_TOKEN;
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const resp: httpm.HttpClientResponse = await http.get(url, headers);
const body = await resp.readBody();
const statusCode = resp.message.statusCode || 500;
if (statusCode >= 400) {
throw new Error(`Failed to list releases from ${url} with status code ${statusCode}: ${body}`);
}
return <Array<GitHubRelease>>JSON.parse(body);
});
const match = releases.find(r => nightlyTagRegex.test(r.tag_name));
if (!match) {
throw new Error(`No '<version>-<sha>-nightly' release found in ${url}`);
}
core.info(`Resolved nightly to ${match.tag_name}`);
return match;
};
const resolveVersion = async (distribution: string, version: string): Promise<string | null> => { const resolveVersion = async (distribution: string, version: string): Promise<string | null> => {
const allTags: Array<string> | null = await getAllTags(distribution); const allTags: Array<string> | null = await getAllTags(distribution);
if (!allTags) { if (!allTags) {

View file

@ -120,7 +120,7 @@ async function verifyCosignSignature(
export const getCertificateIdentity = (distribution: string, tag: string): string => { export const getCertificateIdentity = (distribution: string, tag: string): string => {
const pro = isPro(distribution); const pro = isPro(distribution);
if (github.isNightlyTag(tag)) { if (tag === 'nightly') {
const workflow = pro ? 'nightly-pro.yml' : 'nightly-oss.yml'; const workflow = pro ? 'nightly-pro.yml' : 'nightly-oss.yml';
const repo = pro ? 'goreleaser-pro-internal' : 'goreleaser'; const repo = pro ? 'goreleaser-pro-internal' : 'goreleaser';
return `https://github.com/goreleaser/${repo}/.github/workflows/${workflow}@refs/heads/main`; return `https://github.com/goreleaser/${repo}/.github/workflows/${workflow}@refs/heads/main`;

View file

@ -4,16 +4,14 @@ import yargs from 'yargs';
import type {Arguments} from 'yargs'; import type {Arguments} from 'yargs';
import * as context from './context'; import * as context from './context';
import * as goreleaser from './goreleaser'; import * as goreleaser from './goreleaser';
import {getRequestedVersion} from './version';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
async function run(): Promise<void> { async function run(): Promise<void> {
try { try {
const inputs: context.Inputs = await context.getInputs(); const inputs: context.Inputs = await context.getInputs();
const version = getRequestedVersion(inputs); const bin = await goreleaser.install(inputs.distribution, inputs.version);
const bin = await goreleaser.install(inputs.distribution, version); core.info(`GoReleaser ${inputs.version} installed successfully`);
core.info(`GoReleaser ${version} installed successfully`);
if (inputs.installOnly) { if (inputs.installOnly) {
const goreleaserDir = path.dirname(bin); const goreleaserDir = path.dirname(bin);

View file

@ -1,56 +0,0 @@
import * as fs from 'fs';
import * as path from 'path';
import {Inputs} from './context';
// Resolves the GoReleaser version to install.
//
// When `version-file` is set, it is read from disk and parsed; the resolved
// value takes precedence over the `version` input. Otherwise, `version` is
// returned as-is (it always has a default — see context.getInputs).
export function getRequestedVersion(inputs: Inputs): string {
if (!inputs.versionFile) {
return inputs.version;
}
const filePath = path.isAbsolute(inputs.versionFile)
? inputs.versionFile
: path.join(inputs.workdir || '.', inputs.versionFile);
if (!fs.existsSync(filePath)) {
throw new Error(`version-file not found: ${filePath}`);
}
const basename = path.basename(filePath);
const content = fs.readFileSync(filePath, 'utf-8');
switch (basename) {
case '.tool-versions':
return parseToolVersions(content, filePath);
default:
throw new Error(`Unsupported version-file: ${filePath} (only .tool-versions is supported)`);
}
}
// Parses a single `goreleaser <version>` entry out of a `.tool-versions` file
// (asdf/mise format). Full-line `#` comments and inline `# ...` suffixes are
// stripped. When a tool lists multiple fallback versions only the first is
// used. Bare semvers are returned with a leading `v`; constraint expressions
// (`~> v2`, `latest`, ...) are returned as-is.
function parseToolVersions(content: string, filePath: string): string {
for (const rawLine of content.split('\n')) {
const line = rawLine.replace(/#.*$/, '').trim();
if (!line) {
continue;
}
const tokens = line.split(/\s+/);
if (tokens[0] !== 'goreleaser') {
continue;
}
const version = tokens[1];
if (!version) {
throw new Error(`No version specified for goreleaser in ${filePath}`);
}
return /^\d/.test(version) ? `v${version}` : version;
}
throw new Error(`No goreleaser entry found in ${filePath}`);
}