Skip to content

ci: serialize release creation so the upload matrix never races #95

ci: serialize release creation so the upload matrix never races

ci: serialize release creation so the upload matrix never races #95

Workflow file for this run

name: Go
on:
push:
branches: [ "main" ]
tags: [ "v*" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Cache Go build artifacts
uses: actions/cache@v5
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.mod') }}
restore-keys: |
${{ runner.os }}-go-
- name: Verify dependencies
run: go mod verify
- name: Build
run: go build -v -buildvcs=false ./...
- name: Test
run: go test -v -race ./...
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: latest
# Single job that owns release creation. It runs once (not a matrix), so
# exactly one job ever creates the release for the tag. The upload-assets
# matrix below then only adds files to this already-existing release and can
# never race to create it (the race that made action-gh-release v3 fail with
# "already_exists (tag_name)").
create-release:
needs: build
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Ensure release exists for tag
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
upload-assets:
needs: create-release
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write
strategy:
matrix:
include:
- os: ubuntu-latest
goos: linux
goarch: amd64
artifact_name: subenum
asset_name: subenum-linux-amd64
- os: windows-latest
goos: windows
goarch: amd64
artifact_name: subenum.exe
asset_name: subenum-windows-amd64.exe
- os: macos-latest
goos: darwin
goarch: arm64
artifact_name: subenum
asset_name: subenum-macos-arm64
- os: ubuntu-latest
goos: darwin
goarch: amd64
artifact_name: subenum
asset_name: subenum-macos-amd64
- os: ubuntu-latest
goos: linux
goarch: arm64
artifact_name: subenum
asset_name: subenum-linux-arm64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Cache Go build artifacts
uses: actions/cache@v5
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.mod') }}
restore-keys: |
${{ runner.os }}-go-
- name: Build
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
run: go build -v -buildvcs=false -o ${{ matrix.artifact_name }}
- name: Rename for release
shell: bash
run: |
if [ "${{ matrix.artifact_name }}" != "${{ matrix.asset_name }}" ]; then
cp ${{ matrix.artifact_name }} ${{ matrix.asset_name }}
fi
- name: Generate checksum
shell: bash
run: sha256sum ${{ matrix.asset_name }} > ${{ matrix.asset_name }}.sha256
# The release already exists (created by create-release), so each matrix leg
# only adds its binary and checksum. No matrix job creates the release, which
# avoids the concurrent-create race entirely.
- name: Upload assets to release
uses: softprops/action-gh-release@v2
with:
files: |
${{ matrix.asset_name }}
${{ matrix.asset_name }}.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}