diff --git a/README.md b/README.md index 1c131a3..ee0a6f3 100644 --- a/README.md +++ b/README.md @@ -6,19 +6,49 @@ Reusable GitHub Actions for CI/CD. - `actions/gpg-ephemeral-key`: Ephemeral key generation for RPM/GPG signing - `actions/sign-rpm`: RPM signing with ephemeral keys +- `workflows/go-build-release.yml`: Reusable workflow for GoReleaser builds ## Versioning & Usage Use major version tags for stability: ```yaml +# For actions - uses: OpenCHAMI/github-actions/actions/gpg-ephemeral-key@v1 - uses: OpenCHAMI/github-actions/actions/sign-rpm@v1 + +# For reusable workflows +jobs: + release: + uses: OpenCHAMI/github-actions/workflows/go-build-release.yml@v2 ``` Pin a commit SHA internally for maximum supply‑chain safety if desired. -## Actions Overview +## Actions and Workflows Overview + +### go-build-release (Reusable Workflow) +Standardized GoReleaser workflow for building and releasing Go applications with: +- Multi-architecture builds (linux/amd64, linux/arm64) +- Flexible pre-build setup steps +- Wraps `goreleaser-action` action with all .gorelease.yaml configurations +- Container image builds and publishing +- Binary and container attestation/signing + +**Usage:** +```yaml +jobs: + release: + uses: OpenCHAMI/github-actions/workflows/go-build-release.yml@v2 + with: + pre-build-commands: | + go install github.com/swaggo/swag/cmd/swag@latest + attestation-binary-path: "dist/cloud-init*" + registry-name: ghcr.io/openchami/cloud-init + +``` + +See the [workflow](workflows/go-build-release.yml) for additional input parameters. ### gpg-ephemeral-key Generates a short‑lived RSA key (default 3072‑bit, 1 day) using an isolated `GNUPGHOME`, signs it with a repo‑scoped subkey you provide, and outputs: diff --git a/workflows/go-build-release.yml b/workflows/go-build-release.yml new file mode 100644 index 0000000..b4b2221 --- /dev/null +++ b/workflows/go-build-release.yml @@ -0,0 +1,139 @@ +name: Go Build and Release with GoReleaser + +on: + workflow_call: + inputs: + go-version: + description: 'Go version to use' + required: false + type: string + default: 'stable' + fetch-depth: + description: 'Git fetch depth for checkout' + required: false + type: number + default: 0 + fetch-tags: + description: 'Whether to fetch tags during checkout' + required: false + type: number + default: 1 + cgo-enabled: + description: 'Set CGO_ENABLED environment variable' + required: false + type: string + default: '' + additional-env-vars: + description: 'Additional environment variables to set (KEY=value format, one per line)' + required: false + type: string + default: '' + pre-build-commands: + description: 'Commands to run before GoReleaser (multiline string)' + required: false + type: string + default: '' + goreleaser-version: + description: 'GoReleaser version to use' + required: false + type: string + default: 'latest' + goreleaser-args: + description: 'Additional arguments for goreleaser' + required: false + type: string + default: 'release --clean' + attestation-binary-path: + description: 'Path for binary attestation' + required: false + type: string + default: 'dist/*' + registry-name: + description: 'Container registry name (e.g., ghcr.io/openchami/project-name) to Generate build provenance for container' + required: true + type: string + +permissions: write-all # Necessary for the generate-build-provenance action with containers + +jobs: + build_and_release: + runs-on: ubuntu-latest + steps: + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ${{ inputs.go-version }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Docker Login + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-tags: ${{ inputs.fetch-tags }} + fetch-depth: ${{ inputs.fetch-depth }} + + - name: Set build environment variables + run: | + echo "GIT_STATE=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi)" >> $GITHUB_ENV + echo "BUILD_HOST=$(hostname)" >> $GITHUB_ENV + echo "GO_VERSION=$(go version | awk '{print $3}')" >> $GITHUB_ENV + echo "BUILD_USER=$(whoami)" >> $GITHUB_ENV + + - name: Set CGO_ENABLED if specified + if: ${{ inputs.cgo-enabled != '' }} + run: echo "CGO_ENABLED=${{ inputs.cgo-enabled }}" >> $GITHUB_ENV + + - name: Set additional environment variables + if: ${{ inputs.additional-env-vars != '' }} + run: | + # Process additional environment variables + echo "${{ inputs.additional-env-vars }}" | while IFS= read -r line; do + if [[ -n "$line" && "$line" == *"="* ]]; then + echo "$line" >> $GITHUB_ENV + fi + done + + - name: Run pre-build commands + if: ${{ inputs.pre-build-commands != '' }} + run: ${{ inputs.pre-build-commands }} + + - name: Release with GoReleaser + uses: goreleaser/goreleaser-action@v6 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + version: ${{ inputs.goreleaser-version }} + args: ${{ inputs.goreleaser-args }} + id: goreleaser + + - name: Process GoReleaser output + id: process_goreleaser_output + run: | + echo "const fs = require('fs');" > process.js + echo 'const artifacts = ${{ steps.goreleaser.outputs.artifacts }}' >> process.js + echo "const firstNonNullDigest = artifacts.find(artifact => artifact.extra && artifact.extra.Digest != null)?.extra.Digest;" >> process.js + echo "console.log(firstNonNullDigest);" >> process.js + echo "fs.writeFileSync('digest.txt', firstNonNullDigest);" >> process.js + node process.js + echo "digest=$(cat digest.txt)" >> $GITHUB_OUTPUT + + - name: Attest Binaries + uses: actions/attest-build-provenance@v1 + with: + subject-path: ${{ inputs.attestation-binary-path }} + + - name: Generate build provenance for container + if: ${{ steps.process_goreleaser_output.outputs.digest != '' && steps.process_goreleaser_output.outputs.digest != 'undefined' }} + uses: actions/attest-build-provenance@v1 + with: + subject-name: ${{ inputs.registry-name }} + subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }} + push-to-registry: true