Compare commits

..
1 Commits
Author SHA1 Message Date
Carlos Alexandro Becker 1acc428802 chore(deps): bump yargs from 17.7.2 to 18.0.0
Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
2025-08-14 10:19:05 -03:00
31 changed files with 6521 additions and 6455 deletions
+4 -2
View File
@@ -1,2 +1,4 @@
/dist/** linguist-generated=true -diff
/lib/** linguist-generated=true -diff
/.yarn/releases/** binary
/.yarn/plugins/** binary
/dist/** linguist-generated=true
/lib/** linguist-generated=true
+6 -16
View File
@@ -3,28 +3,18 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: monthly
interval: "daily"
time: "06:00"
timezone: "Europe/Paris"
labels:
- "dependencies"
commit-message:
prefix: "ci"
include: "scope"
groups:
actions:
patterns:
- "*"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: monthly
interval: "daily"
time: "06:00"
timezone: "Europe/Paris"
allow:
- dependency-type: "production"
labels:
- "dependencies"
commit-message:
prefix: "chore"
include: "scope"
groups:
npm:
patterns:
- "*"
+19 -24
View File
@@ -32,21 +32,22 @@ jobs:
- windows-latest
version:
- latest
- '~> 2.13'
- '~> 2.6'
- '~> 1.26'
distribution:
- goreleaser
- goreleaser-pro
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v5
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
uses: actions/setup-go@v5
with:
go-version: stable
go-version: 1.18
-
name: Check
uses: ./
@@ -73,28 +74,22 @@ jobs:
matrix:
version:
- latest
- '~> 2.13'
- '~> 2.6'
- '~> 1.26'
distribution:
- goreleaser
- goreleaser-pro
cosign:
- true
- false
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v5
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
uses: actions/setup-go@v5
with:
go-version: 1.18
-
name: Install cosign
if: matrix.cosign
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
-
name: GoReleaser
if: ${{ !(github.event_name == 'pull_request' && matrix.distribution == 'goreleaser-pro') }}
@@ -122,18 +117,18 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v5
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
uses: actions/setup-go@v5
with:
go-version: 1.18
-
name: Import GPG key
id: import_gpg
uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd # v7.0.0
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY_TEST }}
passphrase: ${{ secrets.PASSPHRASE_TEST }}
@@ -161,12 +156,12 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v5
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
uses: actions/setup-go@v5
with:
go-version: 1.18
-
@@ -183,7 +178,7 @@ jobs:
workdir: ./test
-
name: Upload assets
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@v4
with:
name: myapp
path: ./test/dist/*
@@ -193,12 +188,12 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v5
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
uses: actions/setup-go@v5
with:
go-version: 1.18
-
@@ -227,12 +222,12 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v5
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
uses: actions/setup-go@v5
with:
go-version: 1.18
-
-46
View File
@@ -1,46 +0,0 @@
name: release major tag
run-name: Move ${{ github.event.inputs.major_version }} to ${{ github.event.inputs.target }}
on:
workflow_dispatch:
inputs:
target:
description: The tag, branch, or SHA the major version should point to (e.g. v7.1.0)
required: true
major_version:
type: choice
description: The major version tag to move
options:
- v7
- v6
- v5
- v4
- v3
- v2
- v1
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: write
jobs:
tag:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
-
name: Git config
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
-
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 }}
-
name: Push
run: git push origin ${{ github.event.inputs.major_version }} --force
+6 -15
View File
@@ -21,26 +21,17 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v5
with:
fetch-depth: 0
-
name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v6.0.0
with:
node-version-file: '.node-version'
cache: npm
-
name: Install cosign
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
-
name: Install dependencies
run: npm ci
-
name: Test
run: npm test
uses: docker/bake-action@v6
with:
source: .
targets: test
-
name: Upload coverage
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
uses: codecov/codecov-action@v5
with:
files: ./coverage/clover.xml
+18 -69
View File
@@ -16,83 +16,32 @@ on:
pull_request:
jobs:
lint:
prepare:
runs-on: ubuntu-latest
outputs:
targets: ${{ steps.generate.outputs.targets }}
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@v5
-
name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v6.0.0
name: List targets
id: generate
uses: docker/bake-action/subaction/list-targets@v6
with:
node-version-file: '.node-version'
cache: npm
-
name: Install dependencies
run: npm ci
-
name: Format check
run: npm run format-check
-
name: Lint
run: npm run lint
target: validate
build:
validate:
runs-on: ubuntu-latest
needs:
- prepare
strategy:
fail-fast: false
matrix:
target: ${{ fromJson(needs.prepare.outputs.targets) }}
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
-
name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v6.0.0
name: Validate
uses: docker/bake-action@v6
with:
node-version-file: '.node-version'
cache: npm
-
name: Install dependencies
run: npm ci --ignore-scripts
-
name: Rebuild dist
run: npm run build
-
name: Compare dist
id: diff
run: |
if [ "$(git diff --ignore-space-at-eol dist | wc -l)" -gt "0" ]; then
echo "Detected uncommitted changes after build. Run 'npm run build' and commit dist/." >&2
git diff dist
exit 1
fi
-
name: Upload built dist on failure
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: dist
path: dist
vendor:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
-
name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v6.0.0
with:
node-version-file: '.node-version'
cache: npm
-
name: Refresh package-lock.json
run: npm install --package-lock-only
-
name: Compare package-lock.json
run: |
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
git diff package-lock.json
exit 1
fi
targets: ${{ matrix.target }}
+11 -1
View File
@@ -4,6 +4,8 @@
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
@@ -33,6 +35,8 @@ jspm_packages/
# Optional eslint cache
.eslintcache
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
@@ -40,4 +44,10 @@ jspm_packages/
.env.test.local
.env.production.local
.env.local
provenance.json
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
-1
View File
@@ -1 +0,0 @@
24
File diff suppressed because one or more lines are too long
+13
View File
@@ -0,0 +1,13 @@
logFilters:
- code: YN0013
level: discard
- code: YN0019
level: discard
- code: YN0076
level: discard
nodeLinker: node-modules
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"
-89
View File
@@ -1,89 +0,0 @@
# Contributing
Thanks for your interest in contributing!
## Prerequisites
- [Node.js](https://nodejs.org/) — version pinned in [`.node-version`](./.node-version).
Tools like [`nvm`](https://github.com/nvm-sh/nvm), [`fnm`](https://github.com/Schniz/fnm),
[`asdf`](https://asdf-vm.com/), or [`mise`](https://mise.jdx.dev/) read this file
automatically.
- [`cosign`](https://docs.sigstore.dev/cosign/installation/) — only required if you
want to run the signature-verification integration tests locally.
## Setup
```sh
npm ci
```
## Pre-commit checklist
Before committing changes to `src/`, `__tests__/`, `package.json`,
`package-lock.json`, or `action.yml`:
```sh
npm run pre-checkin
```
That runs `format` + `build` + `test` — the same checks CI runs.
Then commit `dist/` along with your source changes; the action runtime loads
`dist/index.js` directly, so it must stay in sync.
If CI's `validate / build` job fails because `dist/` differs from a fresh
build, just download the `dist` artifact from the failed run and commit it —
or rerun `npm run build` locally with the Node version in `.node-version`.
## npm scripts
| Script | Purpose |
| ------------------- | ------------------------------------------------ |
| `npm run build` | Bundle `src/` to `dist/index.js` via `ncc` |
| `npm run format` | Run Prettier (write) |
| `npm run format-check` | Run Prettier (check only, used in CI) |
| `npm run lint` | Run ESLint (check only, used in CI) |
| `npm run lint:fix` | Run ESLint with `--fix` |
| `npm test` | Run Jest with coverage |
| `npm run pre-checkin` | `format` + `lint:fix` + `build` + `test` |
## Tests
`npm test` runs the full Jest suite, including integration tests that:
- Download real GoReleaser releases from GitHub
- Verify `checksums.txt` against the downloaded archive
- Verify the cosign sigstore bundle (skipped if `cosign` isn't on `PATH`,
but the CI image always has it installed)
These need outbound network access. Offline / restrictive-proxy runs will
have those tests fail — that's expected.
## Commit messages
Use [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`,
`fix:`, `test:`, `docs:`, `chore:`, `ci:`, …). Keep the subject ≤72 chars.
## Pull requests
- Target `master`.
- Make sure `npm run pre-checkin` passes.
- One logical change per PR is easier to review.
- The `signing` CI job and `goreleaser-pro` matrix entries are skipped on PRs
from forks because they need repository secrets — that's expected and not
something you need to fix.
## Releasing (maintainers)
1. Create a new GitHub Release with a semver tag (e.g. `v7.1.0`) — either
through the UI or `gh release create v7.1.0 --generate-notes`.
2. Once the release exists, run the [**release major tag**](./.github/workflows/release-major-tag.yml)
workflow from the Actions tab:
- `target`: the new tag (e.g. `v7.1.0`)
- `major_version`: the major version to repoint (e.g. `v7`)
This force-pushes the major tag to the new release so consumers using
`goreleaser/goreleaser-action@v7` pick up the change.
The same workflow doubles as a rollback tool — pass an older tag as
`target` to revert the major.
+17 -57
View File
@@ -16,7 +16,6 @@ ___
* [Usage](#usage)
* [Workflow](#workflow)
* [Verification](#verification)
* [Run on new tag](#run-on-new-tag)
* [Signing](#signing)
* [Upload artifacts](#upload-artifacts)
@@ -55,15 +54,15 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@v6
uses: actions/setup-go@v5
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
uses: goreleaser/goreleaser-action@v6
with:
# either 'goreleaser' (default) or 'goreleaser-pro'
distribution: goreleaser
@@ -78,44 +77,6 @@ jobs:
> **IMPORTANT**: note the `fetch-depth: 0` input in `Checkout` step. It is required for the changelog to work correctly.
### Verification
The action verifies the integrity of the downloaded GoReleaser archive
against the published `checksums.txt` automatically — no configuration
required.
If [`cosign`](https://docs.sigstore.dev/cosign/) is available on `PATH`, the
action will additionally verify the cosign sigstore signature of the
checksums file against the GoReleaser release workflow's OIDC identity. If
`cosign` isn't installed, this step is silently skipped.
> **Note**: cosign signature verification requires GoReleaser **v2.13.0 or
> newer** (and the matching `nightly`). Earlier releases ship a `.sig`
> detached signature signed with cosign v2, which is not compatible with
> the cosign v3 sigstore-bundle format the action verifies. For older
> versions the cosign step is silently skipped — only the `checksums.txt`
> SHA-256 verification runs.
To enable signature verification, install cosign before running the action:
```yaml
-
name: Install cosign
uses: sigstore/cosign-installer@v3
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
with:
distribution: goreleaser
version: '~> v2'
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
Both checksum and signature verification work for tagged releases (≥ v2.13.0)
and the `nightly` channel.
### Run on new tag
If you want to run GoReleaser only on new tag, you can use this event:
@@ -132,7 +93,7 @@ Or with a condition on GoReleaser step:
```yaml
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
uses: goreleaser/goreleaser-action@v6
if: startsWith(github.ref, 'refs/tags/')
with:
version: '~> v2'
@@ -152,13 +113,13 @@ the [Import GPG](https://github.com/crazy-max/ghaction-import-gpg) GitHub Action
-
name: Import GPG key
id: import_gpg
uses: crazy-max/ghaction-import-gpg@v7
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PASSPHRASE }}
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
uses: goreleaser/goreleaser-action@v6
with:
version: '~> v2'
args: release --clean
@@ -183,7 +144,7 @@ purposes. You can do that with the [actions/upload-artifact](https://github.com/
```yaml
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
uses: goreleaser/goreleaser-action@v6
with:
version: '~> v2'
args: release --clean
@@ -192,7 +153,7 @@ purposes. You can do that with the [actions/upload-artifact](https://github.com/
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
name: Upload assets
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v4
with:
name: myapp
path: myfolder/dist/*
@@ -204,7 +165,7 @@ purposes. You can do that with the [actions/upload-artifact](https://github.com/
steps:
-
name: Install GoReleaser
uses: goreleaser/goreleaser-action@v7
uses: goreleaser/goreleaser-action@v6
with:
install-only: true
-
@@ -258,7 +219,7 @@ secret named `GH_PAT`, the step will look like this:
```yaml
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v7
uses: goreleaser/goreleaser-action@v6
with:
version: '~> v2'
args: release --clean
@@ -272,16 +233,15 @@ If you need the auto-snapshot feature, take a look at [this example repository](
## Development
See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full development workflow.
Quick reference:
```
# install dependencies
npm ci
# format code and build javascript artifacts
docker buildx bake pre-checkin
# format, build dist/, and run tests
npm run pre-checkin
# validate all code has correctly formatted and built
docker buildx bake validate
# run tests
docker buildx bake test
```
## License
+2 -2
View File
@@ -22,7 +22,7 @@ describe('getRelease', () => {
it('unknown GoReleaser release', async () => {
await expect(github.getRelease('goreleaser', 'foo')).rejects.toThrow(
new Error('Cannot find GoReleaser release foo in https://goreleaser.com/releases.json')
new Error('Cannot find GoReleaser release foo in https://goreleaser.com/static/releases.json')
);
});
@@ -100,7 +100,7 @@ describe('getRelease', () => {
it('unknown GoReleaser Pro release', async () => {
await expect(github.getRelease('goreleaser-pro', 'foo')).rejects.toThrow(
new Error('Cannot find GoReleaser release foo in https://goreleaser.com/releases-pro.json')
new Error('Cannot find GoReleaser release foo in https://goreleaser.com/static/releases-pro.json')
);
});
});
+19 -96
View File
@@ -1,23 +1,35 @@
import {describe, expect, it} from '@jest/globals';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as io from '@actions/io';
import * as goreleaser from '../src/goreleaser';
describe('install', () => {
it('acquires v0.182.0 version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', 'v0.182.0');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
it('acquires latest version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', 'latest');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
it('acquires latest v2 version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', '~> v2');
it('acquires v0.182.0-pro version of GoReleaser Pro', async () => {
const bin = await goreleaser.install('goreleaser-pro', 'v0.182.0-pro');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
it('acquires v2.13.0 (minimum cosign-verifiable) version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', 'v2.13.0');
it('acquires latest v1 version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', '~> v1');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
it('acquires latest v1 version of GoReleaser Pro', async () => {
const bin = await goreleaser.install('goreleaser-pro', '~> v1');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
it('acquires latest v2 version of GoReleaser', async () => {
const bin = await goreleaser.install('goreleaser', '~> v2');
expect(fs.existsSync(bin)).toBe(true);
}, 100000);
@@ -41,92 +53,3 @@ describe('distribSuffix', () => {
expect(goreleaser.distribSuffix('goreleaser')).toEqual('');
});
});
describe('findChecksum', () => {
const sample = [
'*malformed-line',
'',
'abc123 goreleaser_Linux_x86_64.tar.gz',
'def456 *goreleaser_Darwin_all.tar.gz',
'789xyz checksums.txt'
].join('\n');
it('finds a checksum by filename', () => {
expect(goreleaser.findChecksum(sample, 'goreleaser_Linux_x86_64.tar.gz')).toEqual('abc123');
});
it('strips a leading asterisk on the filename (binary mode)', () => {
expect(goreleaser.findChecksum(sample, 'goreleaser_Darwin_all.tar.gz')).toEqual('def456');
});
it('returns undefined when not present', () => {
expect(goreleaser.findChecksum(sample, 'missing.tar.gz')).toBeUndefined();
});
});
describe('getCertificateIdentity', () => {
it('returns the OSS workflow identity for tagged releases', () => {
expect(goreleaser.getCertificateIdentity('goreleaser', 'v2.15.3')).toEqual(
'https://github.com/goreleaser/goreleaser/.github/workflows/release.yml@refs/tags/v2.15.3'
);
});
it('returns the Pro internal workflow identity for tagged releases', () => {
expect(goreleaser.getCertificateIdentity('goreleaser-pro', 'v2.15.3')).toEqual(
'https://github.com/goreleaser/goreleaser-pro-internal/.github/workflows/release-pro.yml@refs/tags/v2.15.3'
);
});
it('uses nightly-oss.yml@refs/heads/main for OSS nightly', () => {
expect(goreleaser.getCertificateIdentity('goreleaser', 'nightly')).toEqual(
'https://github.com/goreleaser/goreleaser/.github/workflows/nightly-oss.yml@refs/heads/main'
);
});
it('uses nightly-pro.yml@refs/heads/main for Pro nightly', () => {
expect(goreleaser.getCertificateIdentity('goreleaser-pro', 'nightly')).toEqual(
'https://github.com/goreleaser/goreleaser-pro-internal/.github/workflows/nightly-pro.yml@refs/heads/main'
);
});
});
describe('verifyChecksum', () => {
const requireCosign = async (): Promise<void> => {
const cosign = await io.which('cosign', false);
if (!cosign) {
throw new Error(
'cosign must be installed in PATH to run this integration test (apk add cosign / sigstore/cosign-installer)'
);
}
};
it('verifies a tagged OSS release end-to-end with cosign', async () => {
await requireCosign();
const bin = await goreleaser.install('goreleaser', 'v2.15.3');
expect(fs.existsSync(bin)).toBe(true);
}, 120000);
it('verifies the OSS nightly release end-to-end with cosign', async () => {
await requireCosign();
const bin = await goreleaser.install('goreleaser', 'nightly');
expect(fs.existsSync(bin)).toBe(true);
}, 120000);
it('throws on checksum mismatch', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gha-'));
const archive = path.join(dir, 'fake.tar.gz');
fs.writeFileSync(archive, 'tampered content');
await expect(
goreleaser.verifyChecksum('goreleaser', 'v2.15.3', archive, 'goreleaser_Linux_x86_64.tar.gz')
).rejects.toThrow(/Checksum mismatch/);
}, 60000);
it('throws when the filename is not in checksums.txt', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gha-'));
const archive = path.join(dir, 'whatever.tar.gz');
fs.writeFileSync(archive, '');
await expect(
goreleaser.verifyChecksum('goreleaser', 'v2.15.3', archive, 'not-a-real-asset.tar.gz')
).rejects.toThrow(/Could not find not-a-real-asset.tar.gz in checksums.txt/);
}, 60000);
});
+1 -1
View File
@@ -34,5 +34,5 @@ outputs:
description: 'Build result metadata'
runs:
using: 'node24'
using: 'node20'
main: 'dist/index.js'
+82
View File
@@ -0,0 +1,82 @@
# syntax=docker/dockerfile:1
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine AS base
RUN apk add --no-cache cpio findutils git
WORKDIR /src
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache <<EOT
corepack enable
yarn --version
yarn config set --home enableTelemetry 0
EOT
FROM base AS deps
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn install && mkdir /vendor && cp yarn.lock /vendor
FROM scratch AS vendor-update
COPY --from=deps /vendor /
FROM deps AS vendor-validate
RUN --mount=type=bind,target=.,rw <<EOT
set -e
git add -A
cp -rf /vendor/* .
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor"'
git status --porcelain -- yarn.lock
exit 1
fi
EOT
FROM deps AS build
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn run build && mkdir /out && cp -Rf dist /out/
FROM scratch AS build-update
COPY --from=build /out /
FROM build AS build-validate
RUN --mount=type=bind,target=.,rw <<EOT
set -e
git add -A
cp -rf /out/* .
if [ -n "$(git status --porcelain -- dist)" ]; then
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'
git status --porcelain -- dist
exit 1
fi
EOT
FROM deps AS format
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn run format \
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' -not -path './.yarn/*' | cpio -pdm /out
FROM scratch AS format-update
COPY --from=format /out /
FROM deps AS lint
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn run lint
FROM deps AS test
ENV RUNNER_TEMP=/tmp/github_runner
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/.yarn/cache \
--mount=type=cache,target=/src/node_modules \
yarn run test --coverage --coverageDirectory=/tmp/coverage
FROM scratch AS test-coverage
COPY --from=test /tmp/coverage /
Generated Vendored
+9 -10
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+1
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+22
View File
@@ -71,6 +71,28 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@fastify/busboy
MIT
Copyright Brian White. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
ansi-regex
MIT
MIT License
Generated Vendored
-3
View File
@@ -1,3 +0,0 @@
{
"type": "module"
}
Generated Vendored
+1
View File
File diff suppressed because one or more lines are too long
+61
View File
@@ -0,0 +1,61 @@
target "_common" {
args = {
BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1
}
}
group "default" {
targets = ["build"]
}
group "pre-checkin" {
targets = ["vendor", "format", "build"]
}
group "validate" {
targets = ["lint", "build-validate", "vendor-validate"]
}
target "build" {
dockerfile = "dev.Dockerfile"
target = "build-update"
output = ["."]
}
target "build-validate" {
inherits = ["_common"]
dockerfile = "dev.Dockerfile"
target = "build-validate"
output = ["type=cacheonly"]
}
target "format" {
dockerfile = "dev.Dockerfile"
target = "format-update"
output = ["."]
}
target "lint" {
dockerfile = "dev.Dockerfile"
target = "lint"
output = ["type=cacheonly"]
}
target "vendor" {
dockerfile = "dev.Dockerfile"
target = "vendor-update"
output = ["."]
}
target "vendor-validate" {
inherits = ["_common"]
dockerfile = "dev.Dockerfile"
target = "vendor-validate"
output = ["type=cacheonly"]
}
target "test" {
dockerfile = "dev.Dockerfile"
target = "test-coverage"
output = ["./coverage"]
}
+2 -15
View File
@@ -1,24 +1,11 @@
import type {Config} from 'jest';
const config: Config = {
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
setupFiles: ['dotenv/config', '<rootDir>/src/test_setup.ts'],
testMatch: ['**/*.test.ts'],
testTimeout: 30000,
transform: {
'^.+\\.ts$': [
'ts-jest',
{
useESM: true
}
]
},
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1'
'^.+\\.ts$': 'ts-jest'
},
verbose: true
};
export default config;
-5886
View File
File diff suppressed because it is too large Load Diff
+17 -16
View File
@@ -2,15 +2,16 @@
"name": "goreleaser-action",
"description": "GitHub Action for GoReleaser, a release automation tool for Go projects",
"main": "src/main.ts",
"type": "module",
"scripts": {
"build": "ncc build src/main.ts --minify --license licenses.txt",
"format": "prettier --write \"**/*.ts\"",
"format-check": "prettier --check \"**/*.ts\"",
"lint": "eslint --max-warnings=0 \"**/*.ts\"",
"lint:fix": "eslint --fix \"**/*.ts\"",
"test": "NODE_OPTIONS='--experimental-vm-modules' jest --coverage",
"pre-checkin": "npm run format && npm run lint:fix && npm run build && npm test"
"build": "ncc build src/main.ts --source-map --minify --license licenses.txt",
"lint": "yarn run prettier && yarn run eslint",
"format": "yarn run prettier:fix && yarn run eslint:fix",
"eslint": "eslint --max-warnings=0 .",
"eslint:fix": "eslint --fix .",
"prettier": "prettier --check \"./**/*.ts\"",
"prettier:fix": "prettier --write \"./**/*.ts\"",
"test": "jest",
"all": "yarn run build && yarn run format && yarn test"
},
"repository": {
"type": "git",
@@ -23,18 +24,18 @@
],
"author": "CrazyMax",
"license": "MIT",
"packageManager": "yarn@3.6.3",
"dependencies": {
"@actions/core": "^3.0.0",
"@actions/exec": "^3.0.0",
"@actions/http-client": "^4.0.0",
"@actions/tool-cache": "^4.0.0",
"js-yaml": "^4.1.1",
"semver": "^7.7.4",
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/http-client": "^2.2.3",
"@actions/tool-cache": "^2.0.2",
"js-yaml": "^4.1.0",
"semver": "^7.7.2",
"yargs": "^18.0.0"
},
"devDependencies": {
"@types/node": "^24.0.0",
"@types/node": "^20.6.0",
"@typescript-eslint/eslint-plugin": "^6.6.0",
"@typescript-eslint/parser": "^6.6.0",
"@vercel/ncc": "^0.38.0",
+2 -2
View File
@@ -59,7 +59,7 @@ export const getReleaseTag = async (distribution: string, version: string): Prom
const tag: string = (await resolveVersion(distribution, version)) || version;
const suffix: string = goreleaser.distribSuffix(distribution);
const url = `https://goreleaser.com/releases${suffix}.json`;
const url = `https://goreleaser.com/static/releases${suffix}.json`;
const releases = await withRetry(async () => {
const http: httpm.HttpClient = new httpm.HttpClient('goreleaser-action');
@@ -108,7 +108,7 @@ interface GitHubTag {
const getAllTags = async (distribution: string): Promise<Array<string>> => {
const suffix: string = goreleaser.distribSuffix(distribution);
const url = `https://goreleaser.com/releases${suffix}.json`;
const url = `https://goreleaser.com/static/releases${suffix}.json`;
core.debug(`Downloading ${url}`);
return withRetry(async () => {
+8 -94
View File
@@ -1,26 +1,26 @@
import * as crypto from 'crypto';
import * as fs from 'fs';
import * as path from 'path';
import * as util from 'util';
import yaml from 'js-yaml';
import * as context from './context';
import * as github from './github';
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as io from '@actions/io';
import * as tc from '@actions/tool-cache';
export async function install(distribution: string, version: string): Promise<string> {
const release: github.GitHubRelease = await github.getRelease(distribution, version);
const filename = getFilename(distribution);
const baseUrl = `https://github.com/goreleaser/${distribution}/releases/download/${release.tag_name}`;
const downloadUrl = `${baseUrl}/${filename}`;
const downloadUrl = util.format(
'https://github.com/goreleaser/%s/releases/download/%s/%s',
distribution,
release.tag_name,
filename
);
core.info(`Downloading ${downloadUrl}`);
const downloadPath: string = await tc.downloadTool(downloadUrl);
core.debug(`Downloaded to ${downloadPath}`);
await verifyChecksum(distribution, release.tag_name, downloadPath, filename);
core.info('Extracting GoReleaser');
let extPath: string;
if (context.osPlat == 'win32') {
@@ -45,92 +45,6 @@ export async function install(distribution: string, version: string): Promise<st
return exePath;
}
export async function verifyChecksum(
distribution: string,
tag: string,
archivePath: string,
filename: string
): Promise<void> {
const baseUrl = `https://github.com/goreleaser/${distribution}/releases/download/${tag}`;
let checksumsPath: string;
try {
core.info(`Downloading ${baseUrl}/checksums.txt`);
checksumsPath = await tc.downloadTool(`${baseUrl}/checksums.txt`);
} catch (e) {
core.warning(`Skipping checksum verification: unable to download checksums.txt: ${e.message}`);
return;
}
const sha256 = crypto.createHash('sha256').update(fs.readFileSync(archivePath)).digest('hex');
const expected = findChecksum(fs.readFileSync(checksumsPath, 'utf8'), filename);
if (!expected) {
throw new Error(`Could not find ${filename} in checksums.txt`);
}
if (expected.toLowerCase() !== sha256.toLowerCase()) {
throw new Error(`Checksum mismatch for ${filename}: expected ${expected}, got ${sha256}`);
}
core.info(`Checksum verified for ${filename}`);
await verifyCosignSignature(distribution, tag, baseUrl, checksumsPath);
}
export const findChecksum = (checksumsContent: string, filename: string): string | undefined => {
const match = checksumsContent
.split('\n')
.map(line => line.trim().split(/\s+/))
.find(parts => parts.length >= 2 && parts[1].replace(/^[*]/, '') === filename);
return match ? match[0] : undefined;
};
async function verifyCosignSignature(
distribution: string,
tag: string,
baseUrl: string,
checksumsPath: string
): Promise<void> {
const cosign = await io.which('cosign', false);
if (!cosign) {
core.info('cosign not found in PATH, skipping signature verification');
return;
}
let bundlePath: string;
try {
core.info(`Downloading ${baseUrl}/checksums.txt.sigstore.json`);
bundlePath = await tc.downloadTool(`${baseUrl}/checksums.txt.sigstore.json`);
} catch (e) {
core.warning(`Skipping cosign signature verification: unable to download sigstore bundle: ${e.message}`);
return;
}
const certificateIdentity = getCertificateIdentity(distribution, tag);
core.info(`Verifying checksums.txt signature with cosign (identity: ${certificateIdentity})`);
await exec.exec(cosign, [
'verify-blob',
'--certificate-identity',
certificateIdentity,
'--certificate-oidc-issuer',
'https://token.actions.githubusercontent.com',
'--bundle',
bundlePath,
checksumsPath
]);
core.info('cosign signature verified');
}
export const getCertificateIdentity = (distribution: string, tag: string): string => {
const pro = isPro(distribution);
if (tag === 'nightly') {
const workflow = pro ? 'nightly-pro.yml' : 'nightly-oss.yml';
const repo = pro ? 'goreleaser-pro-internal' : 'goreleaser';
return `https://github.com/goreleaser/${repo}/.github/workflows/${workflow}@refs/heads/main`;
}
if (pro) {
return `https://github.com/goreleaser/goreleaser-pro-internal/.github/workflows/release-pro.yml@refs/tags/${tag}`;
}
return `https://github.com/goreleaser/goreleaser/.github/workflows/release.yml@refs/tags/${tag}`;
};
export const distribSuffix = (distribution: string): string => {
return isPro(distribution) ? '-pro' : '';
};
@@ -167,7 +81,7 @@ const getFilename = (distribution: string): string => {
const platform: string = context.osPlat == 'win32' ? 'Windows' : context.osPlat == 'darwin' ? 'Darwin' : 'Linux';
const ext: string = context.osPlat == 'win32' ? 'zip' : 'tar.gz';
const suffix: string = distribSuffix(distribution);
return `goreleaser${suffix}_${platform}_${arch}.${ext}`;
return util.format('goreleaser%s_%s_%s.%s', suffix, platform, arch, ext);
};
export async function getDistPath(yamlfile: string): Promise<string> {
+1 -4
View File
@@ -1,7 +1,6 @@
import * as fs from 'fs';
import * as path from 'path';
import yargs from 'yargs';
import type {Arguments} from 'yargs';
import * as context from './context';
import * as goreleaser from './goreleaser';
import * as core from '@actions/core';
@@ -29,9 +28,7 @@ async function run(): Promise<void> {
}
let yamlfile: string | unknown;
const argv: Arguments<{config?: string}> = yargs(inputs.args).parseSync() as Arguments<{
config?: string;
}>;
const argv: {config: string} = yargs.parse(inputs.args) as never;
if (argv.config) {
yamlfile = argv.config;
} else {
+1 -1
View File
@@ -1,4 +1,4 @@
import * as tmp from 'tmp';
import tmp = require('tmp');
tmp.setGracefulCleanup();
const tmpdir = tmp.dirSync({template: 'goreleaser-XXXXXX'});
+2 -5
View File
@@ -1,8 +1,8 @@
{
"compilerOptions": {
"esModuleInterop": true,
"target": "ES2024",
"module": "ESNext",
"target": "es6",
"module": "commonjs",
"newLine": "lf",
"outDir": "./lib",
"rootDir": "./src",
@@ -10,9 +10,6 @@
"noImplicitAny": false,
"resolveJsonModule": true,
"useUnknownInCatchVariables": false,
"moduleResolution": "node",
"strict": false,
"skipLibCheck": true
},
"exclude": [
"node_modules",
+5655
View File
File diff suppressed because it is too large Load Diff