From 857d10fd453d2d9a71854c20a9968cc1bedec67f Mon Sep 17 00:00:00 2001 From: Takumi Takahashi Date: Thu, 1 May 2025 12:08:30 +0900 Subject: [PATCH 1/4] feat: Add GitHub Actions workflow and Makefile support for multi-platform release builds - Introduced `.github/workflows/build.yaml` for CI/CD, including build, checksum, and publish jobs - Supports Go cross-compilation for multiple OS/arch targets - Includes artifact attestation and checksum generation - Publishes artifacts to GitHub Releases on tag push - Extended `Makefile` with `release` target to generate static binaries per target - Supports GOOS/GOARCH/GOARM detection and naming --- .github/workflows/build.yaml | 171 +++++++++++++++++++++++++++++++++++ Makefile | 23 +++++ 2 files changed, 194 insertions(+) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..d5653e3 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,171 @@ +--- +name: build + +on: + push: + branches: [main] # pushes TO main + pull_request: + branches: [main] # pull requests AGAINST main + release: + types: [published] # for release build + +# cancel CI runs when a new commit is pushed to any branch except main +concurrency: + group: 'build-${{ github.ref }}' + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 5 + + permissions: + contents: read # for uses: actions/checkout + id-token: write # for actions/attest-build-provenance + attestations: write # for actions/attest-build-provenance + + strategy: + fail-fast: false + matrix: + # Static binaries are built with the `stable` version + # If you want to add a target, add it below. + include: + - {goos: 'darwin', goarch: 'amd64'} + - {goos: 'darwin', goarch: 'arm64'} + - {goos: 'linux', goarch: 'amd64'} + - {goos: 'linux', goarch: 'arm', goarm: '6'} + - {goos: 'linux', goarch: 'arm', goarm: '7'} + - {goos: 'linux', goarch: 'arm64'} + - {goos: 'linux', goarch: 'riscv64'} + - {goos: 'windows', goarch: 'amd64'} + - {goos: 'windows', goarch: 'arm64',} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + # Security measures + # See also: https://github.com/actions/checkout/issues/485 + persist-credentials: false + + - name: Setup golang + uses: actions/setup-go@v5 + with: + go-version: stable + # Disabled in multi-platform builds due to complex caching strategies + cache: false + + - run: make release + env: + DIST_PATH: dist + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + GOARM: ${{ matrix.goarch == 'arm' && matrix.goarm || '' }} + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v2 + # Since the necessary permissions cannot be set in the pull_request event, it is limited to push events. + if: ${{ !startsWith(github.event_name, 'pull') }} + with: + subject-path: dist/go-httpbin-* + + - name: Check artifacts + run: | + file dist/go-httpbin-* + stat dist/go-httpbin-* + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: go-httpbin-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarch == 'arm' && format('v{0}', matrix.goarm) || '' }} + path: dist/ + + checksum: + needs: [build] + runs-on: ubuntu-latest + timeout-minutes: 5 + + permissions: + id-token: write # for uses: aactions/attest-build-provenance + attestations: write # for uses: aactions/attest-build-provenance + + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: dist/ + pattern: go-httpbin-* + merge-multiple: true + + - name: Check artifacts + run: tree --charset ASCII dist/ + + - name: Verify artifacts + # Since the necessary permissions cannot be set in the pull_request event, it is limited to push events. + if: ${{ !startsWith(github.event_name, 'pull') }} + run: | + cd dist + for f in $(find . -type f -name 'go-httpbin-*' -printf '%f\n' | sort); do + gh attestation verify "$f" -R "${GITHUB_REPOSITORY}"; + done + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Generate sha256 checksums + run: | + cd dist + echo -n > SHA256SUMS + for f in $(find . -type f -name 'go-httpbin-*' -printf '%f\n' | sort); do + sha256sum "$f" | tee -a SHA256SUMS; + done + + - name: Verify sha256 checksums + run: cd dist && sha256sum -c SHA256SUMS + + - name: Generate artifact attestation + # Since the necessary permissions cannot be set in the pull_request event, it is limited to push events. + if: ${{ !startsWith(github.event_name, 'pull') }} + uses: actions/attest-build-provenance@v2 + with: + subject-path: dist/SHA256SUMS + + - name: Upload sha256 checksum + uses: actions/upload-artifact@v4 + with: + name: checksum-sha256sums + path: dist/SHA256SUMS + + publish: + needs: [build, checksum] + runs-on: ubuntu-latest + timeout-minutes: 5 + + permissions: + contents: write # for gh release upload + id-token: write # for actions/attest-build-provenance + attestations: write # for actions/attest-build-provenance + + steps: + - name: Download binary artifacts + uses: actions/download-artifact@v4 + with: + path: dist/ + pattern: go-httpbin-* + merge-multiple: true + + - name: Download checksum artifacts + uses: actions/download-artifact@v4 + with: + path: dist/ + pattern: checksum-* + merge-multiple: true + + - name: Check artifacts + run: tree --charset ASCII dist/ + + - name: Publish artifacts + if: startsWith(github.ref, 'refs/tags/') + run: |- + gh release upload "$(echo "${GITHUB_REF}" | sed -E 's!refs/tags/!!')" dist/* -R "${GITHUB_REPOSITORY}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Makefile b/Makefile index 04a3041..48b80f4 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,21 @@ STATICCHECK := go run honnef.co/go/tools/cmd/staticcheck@2025.1.1 HOST ?= 127.0.0.1 PORT ?= 8080 +# Determine the name of the static binary for the release build +GOOS ?= $(shell go env GOOS) +GOARCH ?= $(shell go env GOARCH) +ifeq (x$(GOOS)x,xwindowsx) +GOENVS ?= GOOS=$(GOOS) GOARCH=$(GOARCH) +BINNAME ?= go-httpbin-$(GOOS)-$(GOARCH).exe +else +ifeq (x$(GOARCH)x,xarmx) +GOENVS ?= GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) +BINNAME ?= go-httpbin-$(GOOS)-$(GOARCH)v$(GOARM) +else +GOENVS ?= GOOS=$(GOOS) GOARCH=$(GOARCH) +BINNAME ?= go-httpbin-$(GOOS)-$(GOARCH) +endif +endif # ============================================================================= # build @@ -99,3 +114,11 @@ imagepush: docker buildx build --push --platform linux/amd64,linux/arm64 -t $(DOCKER_TAG) . docker buildx rm httpbin .PHONY: imagepush + +# ============================================================================= +# release build +# ============================================================================= +release: + mkdir -p $(DIST_PATH) + CGO_ENABLED=0 $(GOENVS) go build -trimpath -ldflags '-s -w -buildid=' -o $(DIST_PATH)/$(BINNAME) ./cmd/go-httpbin +.PHONY: release From 32df30a7d100bd1a1cb2559e76fb1a13218d906e Mon Sep 17 00:00:00 2001 From: Takumi Takahashi Date: Thu, 22 May 2025 12:59:59 +0900 Subject: [PATCH 2/4] Update .github/workflows/build.yaml Co-authored-by: Will McCutchen --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d5653e3..f5f04ec 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -105,7 +105,7 @@ jobs: if: ${{ !startsWith(github.event_name, 'pull') }} run: | cd dist - for f in $(find . -type f -name 'go-httpbin-*' -printf '%f\n' | sort); do + for f in go-httpbin-*; do gh attestation verify "$f" -R "${GITHUB_REPOSITORY}"; done env: From e9fcdfee41b3803a8ea346d4c1ad0b1a2f573e46 Mon Sep 17 00:00:00 2001 From: Takumi Takahashi Date: Thu, 22 May 2025 13:10:18 +0900 Subject: [PATCH 3/4] Update .github/workflows/build.yaml Co-authored-by: Will McCutchen --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f5f04ec..b19f535 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -65,7 +65,7 @@ jobs: - name: Generate artifact attestation uses: actions/attest-build-provenance@v2 # Since the necessary permissions cannot be set in the pull_request event, it is limited to push events. - if: ${{ !startsWith(github.event_name, 'pull') }} + if: ${{ github.event_name != 'pull_request' }} with: subject-path: dist/go-httpbin-* From 24ba6b47e9755fdc0e83e29560ba4e1f1267476e Mon Sep 17 00:00:00 2001 From: Takumi Takahashi Date: Thu, 22 May 2025 13:12:05 +0900 Subject: [PATCH 4/4] Update .github/workflows/build.yaml --- .github/workflows/build.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b19f535..7338cb1 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -114,7 +114,6 @@ jobs: - name: Generate sha256 checksums run: | cd dist - echo -n > SHA256SUMS for f in $(find . -type f -name 'go-httpbin-*' -printf '%f\n' | sort); do sha256sum "$f" | tee -a SHA256SUMS; done