mirror of
https://github.com/goreleaser/goreleaser-action.git
synced 2026-05-14 23:00:33 +00:00
Compare commits
22 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cc7ebb73d | ||
|
|
702f5f91c9 | ||
|
|
1a80836c5c | ||
|
|
a71152e827 | ||
|
|
4c6ab561ad | ||
|
|
4f96abf297 | ||
|
|
15fa2a96d4 | ||
|
|
e24998b8b6 | ||
|
|
be2e8a39ba | ||
|
|
5e53f8eea2 | ||
|
|
4068afa2f0 | ||
|
|
213ec80f56 | ||
|
|
4b462d3d1d | ||
|
|
01cbe076be | ||
|
|
2a473d70e3 | ||
|
|
fdcf0b9df9 | ||
|
|
9881cc5376 | ||
|
|
07f3f34e99 | ||
|
|
47f0a77cfc | ||
|
|
4be059cded | ||
|
|
6c92f1d350 | ||
|
|
ff4cb9c029 |
24 changed files with 801 additions and 360 deletions
109
.github/workflows/ci.yml
vendored
109
.github/workflows/ci.yml
vendored
|
|
@ -32,31 +32,26 @@ jobs:
|
||||||
- windows-latest
|
- windows-latest
|
||||||
version:
|
version:
|
||||||
- latest
|
- latest
|
||||||
- '~> 2.6'
|
- '~> 2.13'
|
||||||
- '~> 1.26'
|
|
||||||
distribution:
|
distribution:
|
||||||
- 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@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.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:
|
||||||
|
|
@ -74,32 +69,33 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
version:
|
version:
|
||||||
- latest
|
- latest
|
||||||
- '~> 2.6'
|
- '~> 2.13'
|
||||||
- '~> 1.26'
|
|
||||||
distribution:
|
distribution:
|
||||||
- goreleaser
|
- goreleaser
|
||||||
- goreleaser-pro
|
- goreleaser-pro
|
||||||
|
cosign:
|
||||||
|
- true
|
||||||
|
- 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@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
|
||||||
with:
|
with:
|
||||||
go-version: 1.18
|
go-version: 1.18
|
||||||
-
|
- name: Install cosign
|
||||||
name: GoReleaser
|
if: matrix.cosign
|
||||||
|
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||||
|
- 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
|
||||||
|
|
@ -115,25 +111,21 @@ 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@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.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@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.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
|
||||||
|
|
@ -141,8 +133,7 @@ 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
|
||||||
|
|
@ -154,31 +145,26 @@ 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@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.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
|
||||||
name: Upload assets
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
|
||||||
with:
|
with:
|
||||||
name: myapp
|
name: myapp
|
||||||
path: ./test/dist/*
|
path: ./test/dist/*
|
||||||
|
|
@ -186,24 +172,20 @@ 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@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.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
|
||||||
|
|
||||||
|
|
@ -220,27 +202,24 @@ 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@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.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:
|
||||||
name: Check
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- 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
|
||||||
|
|
||||||
|
|
|
||||||
46
.github/workflows/dependabot-build.yml
vendored
46
.github/workflows/dependabot-build.yml
vendored
|
|
@ -1,46 +0,0 @@
|
||||||
name: dependabot-build
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- 'package.json'
|
|
||||||
|
|
||||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.actor == 'dependabot[bot]'
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
ref: ${{ github.head_ref }}
|
|
||||||
-
|
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
|
||||||
-
|
|
||||||
name: Vendor
|
|
||||||
uses: docker/bake-action@5be5f02ff8819ecd3092ea6b2e6261c31774f2b4 # v6.10.0
|
|
||||||
with:
|
|
||||||
targets: vendor
|
|
||||||
-
|
|
||||||
name: Pre-checkin
|
|
||||||
uses: docker/bake-action@5be5f02ff8819ecd3092ea6b2e6261c31774f2b4 # v6.10.0
|
|
||||||
with:
|
|
||||||
targets: pre-checkin
|
|
||||||
-
|
|
||||||
name: Commit and push changes
|
|
||||||
run: |
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
git add -A
|
|
||||||
if git diff --cached --quiet; then
|
|
||||||
echo "No changes to commit"
|
|
||||||
else
|
|
||||||
git commit -m "chore: update dist and vendor"
|
|
||||||
git push
|
|
||||||
fi
|
|
||||||
42
.github/workflows/release-major-tag.yml
vendored
Normal file
42
.github/workflows/release-major-tag.yml
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
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
|
||||||
25
.github/workflows/test.yml
vendored
25
.github/workflows/test.yml
vendored
|
|
@ -19,19 +19,24 @@ 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
|
||||||
name: Test
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
uses: docker/bake-action@5be5f02ff8819ecd3092ea6b2e6261c31774f2b4 # v6.10.0
|
|
||||||
with:
|
with:
|
||||||
source: .
|
node-version-file: '.node-version'
|
||||||
targets: test
|
cache: npm
|
||||||
-
|
- name: Install cosign
|
||||||
name: Upload coverage
|
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||||
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
- name: Test
|
||||||
|
run: npm test
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Upload coverage
|
||||||
|
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
|
||||||
with:
|
with:
|
||||||
files: ./coverage/clover.xml
|
files: ./coverage/clover.xml
|
||||||
|
|
|
||||||
78
.github/workflows/validate.yml
vendored
78
.github/workflows/validate.yml
vendored
|
|
@ -16,32 +16,68 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
prepare:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
|
||||||
targets: ${{ steps.generate.outputs.targets }}
|
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
-
|
- name: Setup Node.js
|
||||||
name: List targets
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
id: generate
|
|
||||||
uses: docker/bake-action/subaction/list-targets@5be5f02ff8819ecd3092ea6b2e6261c31774f2b4 # v6.10.0
|
|
||||||
with:
|
with:
|
||||||
target: validate
|
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
|
||||||
|
|
||||||
validate:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
|
||||||
- prepare
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
target: ${{ fromJson(needs.prepare.outputs.targets) }}
|
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout
|
||||||
name: Validate
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
uses: docker/bake-action@5be5f02ff8819ecd3092ea6b2e6261c31774f2b4 # v6.10.0
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0
|
||||||
with:
|
with:
|
||||||
targets: ${{ matrix.target }}
|
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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
|
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@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # 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
|
||||||
|
|
|
||||||
1
.node-version
Normal file
1
.node-version
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
24
|
||||||
89
CONTRIBUTING.md
Normal file
89
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
# 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.
|
||||||
96
README.md
96
README.md
|
|
@ -16,6 +16,7 @@ ___
|
||||||
|
|
||||||
* [Usage](#usage)
|
* [Usage](#usage)
|
||||||
* [Workflow](#workflow)
|
* [Workflow](#workflow)
|
||||||
|
* [Verification](#verification)
|
||||||
* [Run on new tag](#run-on-new-tag)
|
* [Run on new tag](#run-on-new-tag)
|
||||||
* [Signing](#signing)
|
* [Signing](#signing)
|
||||||
* [Upload artifacts](#upload-artifacts)
|
* [Upload artifacts](#upload-artifacts)
|
||||||
|
|
@ -54,15 +55,15 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
-
|
||||||
name: Set up Go
|
name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
-
|
-
|
||||||
name: Run GoReleaser
|
name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v6
|
uses: goreleaser/goreleaser-action@v7
|
||||||
with:
|
with:
|
||||||
# either 'goreleaser' (default) or 'goreleaser-pro'
|
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
|
|
@ -77,6 +78,49 @@ jobs:
|
||||||
|
|
||||||
> **IMPORTANT**: note the `fetch-depth: 0` input in `Checkout` step. It is required for the changelog to work correctly.
|
> **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.
|
||||||
|
|
||||||
|
> **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:
|
||||||
|
|
||||||
|
```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
|
### Run on new tag
|
||||||
|
|
||||||
If you want to run GoReleaser only on new tag, you can use this event:
|
If you want to run GoReleaser only on new tag, you can use this event:
|
||||||
|
|
@ -93,7 +137,7 @@ Or with a condition on GoReleaser step:
|
||||||
```yaml
|
```yaml
|
||||||
-
|
-
|
||||||
name: Run GoReleaser
|
name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v6
|
uses: goreleaser/goreleaser-action@v7
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
with:
|
with:
|
||||||
version: '~> v2'
|
version: '~> v2'
|
||||||
|
|
@ -113,13 +157,13 @@ the [Import GPG](https://github.com/crazy-max/ghaction-import-gpg) GitHub Action
|
||||||
-
|
-
|
||||||
name: Import GPG key
|
name: Import GPG key
|
||||||
id: import_gpg
|
id: import_gpg
|
||||||
uses: crazy-max/ghaction-import-gpg@v6
|
uses: crazy-max/ghaction-import-gpg@v7
|
||||||
with:
|
with:
|
||||||
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
|
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
passphrase: ${{ secrets.PASSPHRASE }}
|
passphrase: ${{ secrets.PASSPHRASE }}
|
||||||
-
|
-
|
||||||
name: Run GoReleaser
|
name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v6
|
uses: goreleaser/goreleaser-action@v7
|
||||||
with:
|
with:
|
||||||
version: '~> v2'
|
version: '~> v2'
|
||||||
args: release --clean
|
args: release --clean
|
||||||
|
|
@ -144,7 +188,7 @@ purposes. You can do that with the [actions/upload-artifact](https://github.com/
|
||||||
```yaml
|
```yaml
|
||||||
-
|
-
|
||||||
name: Run GoReleaser
|
name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v6
|
uses: goreleaser/goreleaser-action@v7
|
||||||
with:
|
with:
|
||||||
version: '~> v2'
|
version: '~> v2'
|
||||||
args: release --clean
|
args: release --clean
|
||||||
|
|
@ -153,7 +197,7 @@ purposes. You can do that with the [actions/upload-artifact](https://github.com/
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-
|
-
|
||||||
name: Upload assets
|
name: Upload assets
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v6
|
||||||
with:
|
with:
|
||||||
name: myapp
|
name: myapp
|
||||||
path: myfolder/dist/*
|
path: myfolder/dist/*
|
||||||
|
|
@ -165,7 +209,7 @@ purposes. You can do that with the [actions/upload-artifact](https://github.com/
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Install GoReleaser
|
name: Install GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v6
|
uses: goreleaser/goreleaser-action@v7
|
||||||
with:
|
with:
|
||||||
install-only: true
|
install-only: true
|
||||||
-
|
-
|
||||||
|
|
@ -183,11 +227,28 @@ 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
|
||||||
|
|
||||||
|
|
@ -219,7 +280,7 @@ secret named `GH_PAT`, the step will look like this:
|
||||||
```yaml
|
```yaml
|
||||||
-
|
-
|
||||||
name: Run GoReleaser
|
name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v6
|
uses: goreleaser/goreleaser-action@v7
|
||||||
with:
|
with:
|
||||||
version: '~> v2'
|
version: '~> v2'
|
||||||
args: release --clean
|
args: release --clean
|
||||||
|
|
@ -233,15 +294,16 @@ If you need the auto-snapshot feature, take a look at [this example repository](
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full development workflow.
|
||||||
|
|
||||||
|
Quick reference:
|
||||||
|
|
||||||
```
|
```
|
||||||
# format code and build javascript artifacts
|
# install dependencies
|
||||||
docker buildx bake pre-checkin
|
npm ci
|
||||||
|
|
||||||
# validate all code has correctly formatted and built
|
# format, build dist/, and run tests
|
||||||
docker buildx bake validate
|
npm run pre-checkin
|
||||||
|
|
||||||
# run tests
|
|
||||||
docker buildx bake test
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ describe('getRelease', () => {
|
||||||
|
|
||||||
it('unknown GoReleaser release', async () => {
|
it('unknown GoReleaser release', async () => {
|
||||||
await expect(github.getRelease('goreleaser', 'foo')).rejects.toThrow(
|
await expect(github.getRelease('goreleaser', 'foo')).rejects.toThrow(
|
||||||
new Error('Cannot find GoReleaser release foo in https://goreleaser.com/static/releases.json')
|
new Error('Cannot find GoReleaser release foo in https://goreleaser.com/releases.json')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -56,16 +56,16 @@ describe('getRelease', () => {
|
||||||
expect(release?.tag_name).not.toEqual('');
|
expect(release?.tag_name).not.toEqual('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns nightly GoReleaser GitHub release', async () => {
|
it('resolves nightly to a <version>-<sha>-nightly release for OSS GoReleaser', 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).not.toEqual('');
|
expect(release.tag_name).toMatch(github.nightlyTagRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns nightly GoReleaser Pro GitHub release', async () => {
|
it('resolves nightly to a <version>-<sha>-nightly release for GoReleaser Pro', 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).not.toEqual('');
|
expect(release.tag_name).toMatch(github.nightlyTagRegex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns v0.182.0 GoReleaser Pro GitHub release', async () => {
|
it('returns v0.182.0 GoReleaser Pro GitHub release', async () => {
|
||||||
|
|
@ -100,7 +100,7 @@ describe('getRelease', () => {
|
||||||
|
|
||||||
it('unknown GoReleaser Pro release', async () => {
|
it('unknown GoReleaser Pro release', async () => {
|
||||||
await expect(github.getRelease('goreleaser-pro', 'foo')).rejects.toThrow(
|
await expect(github.getRelease('goreleaser-pro', 'foo')).rejects.toThrow(
|
||||||
new Error('Cannot find GoReleaser release foo in https://goreleaser.com/static/releases-pro.json')
|
new Error('Cannot find GoReleaser release foo in https://goreleaser.com/releases-pro.json')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,53 @@
|
||||||
import {describe, expect, it} from '@jest/globals';
|
import {describe, expect, it} from '@jest/globals';
|
||||||
import * as fs from 'fs';
|
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';
|
import * as goreleaser from '../src/goreleaser';
|
||||||
|
|
||||||
describe('install', () => {
|
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 () => {
|
it('acquires latest version of GoReleaser', async () => {
|
||||||
const bin = await goreleaser.install('goreleaser', 'latest');
|
const bin = await goreleaser.install('goreleaser', 'latest');
|
||||||
expect(fs.existsSync(bin)).toBe(true);
|
expect(fs.existsSync(bin)).toBe(true);
|
||||||
}, 100000);
|
}, 100000);
|
||||||
|
|
||||||
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 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 () => {
|
it('acquires latest v2 version of GoReleaser', async () => {
|
||||||
const bin = await goreleaser.install('goreleaser', '~> v2');
|
const bin = await goreleaser.install('goreleaser', '~> v2');
|
||||||
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 () => {
|
||||||
|
const bin = await goreleaser.install('goreleaser', 'v2.13.0');
|
||||||
|
expect(fs.existsSync(bin)).toBe(true);
|
||||||
|
}, 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);
|
||||||
|
|
@ -53,3 +68,100 @@ describe('distribSuffix', () => {
|
||||||
expect(goreleaser.distribSuffix('goreleaser')).toEqual('');
|
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 tag', () => {
|
||||||
|
expect(goreleaser.getCertificateIdentity('goreleaser', 'v2.16.0-abc1234-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 tag', () => {
|
||||||
|
expect(goreleaser.getCertificateIdentity('goreleaser-pro', 'v2.16.0-eaeb08c50-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('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 () => {
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
|
||||||
117
__tests__/version.test.ts
Normal file
117
__tests__/version.test.ts
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
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/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -15,6 +15,12 @@ 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
|
||||||
|
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
ARG NODE_VERSION=24
|
|
||||||
|
|
||||||
FROM node:${NODE_VERSION}-alpine AS base
|
|
||||||
RUN apk add --no-cache cpio findutils git
|
|
||||||
WORKDIR /src
|
|
||||||
|
|
||||||
FROM base AS deps
|
|
||||||
RUN --mount=type=bind,target=.,rw \
|
|
||||||
--mount=type=cache,target=/src/node_modules \
|
|
||||||
npm install && mkdir /vendor && cp package-lock.json /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 -- package-lock.json)" ]; then
|
|
||||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor"'
|
|
||||||
git status --porcelain -- package-lock.json
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
EOT
|
|
||||||
|
|
||||||
FROM deps AS build
|
|
||||||
RUN --mount=type=bind,target=.,rw \
|
|
||||||
--mount=type=cache,target=/src/node_modules \
|
|
||||||
npm 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/node_modules \
|
|
||||||
npm run format \
|
|
||||||
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' | 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/node_modules \
|
|
||||||
npm 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/node_modules \
|
|
||||||
npm run test -- --coverage --coverageDirectory=/tmp/coverage
|
|
||||||
|
|
||||||
FROM scratch AS test-coverage
|
|
||||||
COPY --from=test /tmp/coverage /
|
|
||||||
10
dist/index.js
generated
vendored
10
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
1
dist/index.js.map
generated
vendored
1
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
1
dist/sourcemap-register.js
generated
vendored
1
dist/sourcemap-register.js
generated
vendored
File diff suppressed because one or more lines are too long
|
|
@ -1,61 +0,0 @@
|
||||||
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"]
|
|
||||||
}
|
|
||||||
18
package-lock.json
generated
18
package-lock.json
generated
|
|
@ -112,7 +112,6 @@
|
||||||
"integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
|
"integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.28.6",
|
"@babel/code-frame": "^7.28.6",
|
||||||
"@babel/generator": "^7.28.6",
|
"@babel/generator": "^7.28.6",
|
||||||
|
|
@ -1431,7 +1430,6 @@
|
||||||
"integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==",
|
"integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~7.16.0"
|
"undici-types": "~7.16.0"
|
||||||
}
|
}
|
||||||
|
|
@ -1473,7 +1471,6 @@
|
||||||
"integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
|
"integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.5.1",
|
"@eslint-community/regexpp": "^4.5.1",
|
||||||
"@typescript-eslint/scope-manager": "6.21.0",
|
"@typescript-eslint/scope-manager": "6.21.0",
|
||||||
|
|
@ -1510,7 +1507,6 @@
|
||||||
"integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
|
"integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "6.21.0",
|
"@typescript-eslint/scope-manager": "6.21.0",
|
||||||
"@typescript-eslint/types": "6.21.0",
|
"@typescript-eslint/types": "6.21.0",
|
||||||
|
|
@ -1690,7 +1686,6 @@
|
||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
|
|
@ -2016,7 +2011,6 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.9.0",
|
"baseline-browser-mapping": "^2.9.0",
|
||||||
"caniuse-lite": "^1.0.30001759",
|
"caniuse-lite": "^1.0.30001759",
|
||||||
|
|
@ -2473,7 +2467,6 @@
|
||||||
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
|
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.6.1",
|
"@eslint-community/regexpp": "^4.6.1",
|
||||||
|
|
@ -2530,7 +2523,6 @@
|
||||||
"integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==",
|
"integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"eslint-config-prettier": "bin/cli.js"
|
"eslint-config-prettier": "bin/cli.js"
|
||||||
},
|
},
|
||||||
|
|
@ -3566,7 +3558,6 @@
|
||||||
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
|
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/core": "^29.7.0",
|
"@jest/core": "^29.7.0",
|
||||||
"@jest/types": "^29.6.3",
|
"@jest/types": "^29.6.3",
|
||||||
|
|
@ -4820,7 +4811,6 @@
|
||||||
"integrity": "sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==",
|
"integrity": "sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"prettier": "bin/prettier.cjs"
|
"prettier": "bin/prettier.cjs"
|
||||||
},
|
},
|
||||||
|
|
@ -5484,7 +5474,6 @@
|
||||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cspotcode/source-map-support": "^0.8.0",
|
"@cspotcode/source-map-support": "^0.8.0",
|
||||||
"@tsconfig/node10": "^1.0.7",
|
"@tsconfig/node10": "^1.0.7",
|
||||||
|
|
@ -5597,7 +5586,6 @@
|
||||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
|
|
@ -5621,9 +5609,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "6.23.0",
|
"version": "6.24.1",
|
||||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz",
|
||||||
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
|
"integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.17"
|
"node": ">=18.17"
|
||||||
|
|
|
||||||
14
package.json
14
package.json
|
|
@ -5,14 +5,12 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "ncc build src/main.ts --minify --license licenses.txt",
|
"build": "ncc build src/main.ts --minify --license licenses.txt",
|
||||||
"lint": "npm run prettier && npm run eslint",
|
"format": "prettier --write \"**/*.ts\"",
|
||||||
"format": "npm run prettier:fix && npm run eslint:fix",
|
"format-check": "prettier --check \"**/*.ts\"",
|
||||||
"eslint": "eslint --max-warnings=0 .",
|
"lint": "eslint --max-warnings=0 \"**/*.ts\"",
|
||||||
"eslint:fix": "eslint --fix .",
|
"lint:fix": "eslint --fix \"**/*.ts\"",
|
||||||
"prettier": "prettier --check \"./**/*.ts\"",
|
"test": "NODE_OPTIONS='--experimental-vm-modules' jest --coverage",
|
||||||
"prettier:fix": "prettier --write \"./**/*.ts\"",
|
"pre-checkin": "npm run format && npm run lint:fix && npm run build && npm test"
|
||||||
"test": "NODE_OPTIONS='--experimental-vm-modules' jest",
|
|
||||||
"all": "npm run build && npm run format && npm test"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ 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;
|
||||||
|
|
@ -16,6 +17,7 @@ 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')
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,13 @@ 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'.");
|
||||||
|
|
@ -40,7 +47,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 {tag_name: version};
|
return resolveNightly(distribution);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
|
@ -59,7 +66,7 @@ export const getReleaseTag = async (distribution: string, version: string): Prom
|
||||||
|
|
||||||
const tag: string = (await resolveVersion(distribution, version)) || version;
|
const tag: string = (await resolveVersion(distribution, version)) || version;
|
||||||
const suffix: string = goreleaser.distribSuffix(distribution);
|
const suffix: string = goreleaser.distribSuffix(distribution);
|
||||||
const url = `https://goreleaser.com/static/releases${suffix}.json`;
|
const url = `https://goreleaser.com/releases${suffix}.json`;
|
||||||
|
|
||||||
const releases = await withRetry(async () => {
|
const releases = await withRetry(async () => {
|
||||||
const http: httpm.HttpClient = new httpm.HttpClient('goreleaser-action');
|
const http: httpm.HttpClient = new httpm.HttpClient('goreleaser-action');
|
||||||
|
|
@ -81,6 +88,39 @@ 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) {
|
||||||
|
|
@ -108,7 +148,7 @@ interface GitHubTag {
|
||||||
|
|
||||||
const getAllTags = async (distribution: string): Promise<Array<string>> => {
|
const getAllTags = async (distribution: string): Promise<Array<string>> => {
|
||||||
const suffix: string = goreleaser.distribSuffix(distribution);
|
const suffix: string = goreleaser.distribSuffix(distribution);
|
||||||
const url = `https://goreleaser.com/static/releases${suffix}.json`;
|
const url = `https://goreleaser.com/releases${suffix}.json`;
|
||||||
core.debug(`Downloading ${url}`);
|
core.debug(`Downloading ${url}`);
|
||||||
|
|
||||||
return withRetry(async () => {
|
return withRetry(async () => {
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,26 @@
|
||||||
|
import * as crypto from 'crypto';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as util from 'util';
|
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import * as context from './context';
|
import * as context from './context';
|
||||||
import * as github from './github';
|
import * as github from './github';
|
||||||
import * as core from '@actions/core';
|
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';
|
import * as tc from '@actions/tool-cache';
|
||||||
|
|
||||||
export async function install(distribution: string, version: string): Promise<string> {
|
export async function install(distribution: string, version: string): Promise<string> {
|
||||||
const release: github.GitHubRelease = await github.getRelease(distribution, version);
|
const release: github.GitHubRelease = await github.getRelease(distribution, version);
|
||||||
const filename = getFilename(distribution);
|
const filename = getFilename(distribution);
|
||||||
const downloadUrl = util.format(
|
const baseUrl = `https://github.com/goreleaser/${distribution}/releases/download/${release.tag_name}`;
|
||||||
'https://github.com/goreleaser/%s/releases/download/%s/%s',
|
const downloadUrl = `${baseUrl}/${filename}`;
|
||||||
distribution,
|
|
||||||
release.tag_name,
|
|
||||||
filename
|
|
||||||
);
|
|
||||||
|
|
||||||
core.info(`Downloading ${downloadUrl}`);
|
core.info(`Downloading ${downloadUrl}`);
|
||||||
const downloadPath: string = await tc.downloadTool(downloadUrl);
|
const downloadPath: string = await tc.downloadTool(downloadUrl);
|
||||||
core.debug(`Downloaded to ${downloadPath}`);
|
core.debug(`Downloaded to ${downloadPath}`);
|
||||||
|
|
||||||
|
await verifyChecksum(distribution, release.tag_name, downloadPath, filename);
|
||||||
|
|
||||||
core.info('Extracting GoReleaser');
|
core.info('Extracting GoReleaser');
|
||||||
let extPath: string;
|
let extPath: string;
|
||||||
if (context.osPlat == 'win32') {
|
if (context.osPlat == 'win32') {
|
||||||
|
|
@ -45,6 +45,92 @@ export async function install(distribution: string, version: string): Promise<st
|
||||||
return exePath;
|
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 (github.isNightlyTag(tag)) {
|
||||||
|
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 => {
|
export const distribSuffix = (distribution: string): string => {
|
||||||
return isPro(distribution) ? '-pro' : '';
|
return isPro(distribution) ? '-pro' : '';
|
||||||
};
|
};
|
||||||
|
|
@ -81,7 +167,7 @@ const getFilename = (distribution: string): string => {
|
||||||
const platform: string = context.osPlat == 'win32' ? 'Windows' : context.osPlat == 'darwin' ? 'Darwin' : 'Linux';
|
const platform: string = context.osPlat == 'win32' ? 'Windows' : context.osPlat == 'darwin' ? 'Darwin' : 'Linux';
|
||||||
const ext: string = context.osPlat == 'win32' ? 'zip' : 'tar.gz';
|
const ext: string = context.osPlat == 'win32' ? 'zip' : 'tar.gz';
|
||||||
const suffix: string = distribSuffix(distribution);
|
const suffix: string = distribSuffix(distribution);
|
||||||
return util.format('goreleaser%s_%s_%s.%s', suffix, platform, arch, ext);
|
return `goreleaser${suffix}_${platform}_${arch}.${ext}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getDistPath(yamlfile: string): Promise<string> {
|
export async function getDistPath(yamlfile: string): Promise<string> {
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,16 @@ 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 bin = await goreleaser.install(inputs.distribution, inputs.version);
|
const version = getRequestedVersion(inputs);
|
||||||
core.info(`GoReleaser ${inputs.version} installed successfully`);
|
const bin = await goreleaser.install(inputs.distribution, version);
|
||||||
|
core.info(`GoReleaser ${version} installed successfully`);
|
||||||
|
|
||||||
if (inputs.installOnly) {
|
if (inputs.installOnly) {
|
||||||
const goreleaserDir = path.dirname(bin);
|
const goreleaserDir = path.dirname(bin);
|
||||||
|
|
|
||||||
56
src/version.ts
Normal file
56
src/version.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
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}`);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue