Skip to content

Release process: single arch, no checksums/signing, no container image, duplicated build config #26

Description

@dolph

Summary

The release workflow ships a single linux/amd64 binary with no integrity verification, no container image, and a hand-maintained build invocation that duplicates build.sh. This limits adoption and creates drift risk.

Concretely:

1. Single platform

.github/workflows/release.yml:90-110 builds only linux/amd64:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ...

Modern Go projects ship at minimum:

  • linux/amd64
  • linux/arm64 (ARM-based EC2/GCE, Apple Silicon Linux VMs, Raspberry Pi)
  • darwin/arm64 + darwin/amd64
  • windows/amd64

Users on anything else have to build from source.

2. No artifact integrity

The release uploads a bare connectivity binary — no SHA256SUMS, no signature, no SBOM. A user has no way to verify a downloaded binary matches what CI built. GitHub's TLS protects in transit, but doesn't prove anything about the build artifact's lineage.

3. No container image

connectivity monitor is almost always deployed as a sidecar/daemon. Every consumer currently has to write their own Dockerfile.

4. Build configuration is duplicated

build.sh and release.yml independently define the same ldflags pattern:

build.sh:

go build -ldflags " \
    -X 'main.GitTag=$GIT_TAG' \
    -X 'main.GitCommit=$GIT_COMMIT' \
    -X 'main.GoVersion=$GO_VERSION' \
    ..."

release.yml:

go build -ldflags="-s -w \
  -X 'main.GitTag=${TAG}' \
  -X 'main.GitCommit=${HEAD_SHA}' \
  -X 'main.GoVersion=${GO_VERSION}' \
  ..."

Differences (intentional?): -s -w, -trimpath, BuildTainted value, timestamp format. When the version metadata schema changes, both have to change in lockstep — drift is inevitable.

Suggested fixes (pick what fits, in order of value)

Multi-arch

Either a matrix:

strategy:
  matrix:
    include:
      - { goos: linux,   goarch: amd64 }
      - { goos: linux,   goarch: arm64 }
      - { goos: darwin,  goarch: amd64 }
      - { goos: darwin,  goarch: arm64 }
      - { goos: windows, goarch: amd64, ext: .exe }

Or switch to goreleaser, which handles multi-arch, archives, checksums, SBOMs, container images, and Homebrew taps from a single .goreleaser.yaml. For this project's scope, goreleaser would replace build.sh AND release.yml and remove the duplication entirely.

Integrity

If using a matrix:

- name: Checksums
  run: sha256sum connectivity-* > SHA256SUMS
- name: Upload to release
  run: gh release upload "${TAG}" connectivity-* SHA256SUMS

Consider cosign sign-blob / Sigstore for keyless signing on top.

Container image

A trivial multi-arch image (alongside the release):

FROM scratch
COPY connectivity /connectivity
ENTRYPOINT ["/connectivity"]

Publish to GHCR (ghcr.io/dolph/connectivity:${TAG}) using docker/build-push-action.

Deduplicate build config

Extract version-ldflags into a single source of truth — a make ldflags target, a version.sh helper, or just commit to goreleaser which centralizes it.

Impact

A maintainer-grade release pipeline catches its own regressions (failed cross-compile, broken ldflags) before users do, and removes future "user can't install on Mac" / "no checksums" / "no image" requests.

Relates to #13 (toolchain), #22 (deps).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions