Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions .github/workflows/binary.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
name: Build Binary

# Two ways in:
#
# 1. Called by release.yaml as a reusable workflow, right after the draft
# release was opened. This is the automatic path, and it runs in the SAME
# workflow run — which is what makes it work at all: a release published
# with GITHUB_TOKEN does NOT trigger new workflow runs, so an `on: release`
# listener would silently never fire.
#
# 2. A manual dispatch, to check that a build still works without touching any
# release. On that path `inputs` is empty, every `inputs.*` reference below
# evaluates to '' rather than erroring, and the binaries are kept as run
# artifacts instead of being attached anywhere.

on:
workflow_call:
inputs:
ref:
description: Commit SHA (or ref) to build. Defaults to the caller's ref.
type: string
required: false
default: ''
release-tag:
description: >-
Tag of an existing — possibly draft — GitHub Release to attach the
binaries and SHA256SUMS to. Empty means build and smoke-test only.
type: string
required: false
default: ''
version:
description: >-
Version to compile in, without a leading `v` (e.g. 1.13.2). Asserted
against what the built binary reports.
type: string
required: false
default: ''
workflow_dispatch:

permissions:
contents: write

jobs:
binary:
name: Build
runs-on: ubuntu-24.04
steps:
- name: Code checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# Empty on dispatch, which makes actions/checkout fall back to its own
# default (the triggering ref and github.sha).
ref: ${{ inputs.ref }}

- name: Setup Go
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: 1.24.11

- name: Resolve the version
id: resolve
env:
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
# A dispatch build carries no version; label it by commit so a stray
# binary can never claim to be a release.
if [ -z "$VERSION" ]; then
VERSION="dev-$(git rev-parse --short HEAD)"
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"

- name: Build release binaries
env:
CGO_ENABLED: 0
VERSION: ${{ steps.resolve.outputs.version }}
run: |
set -euo pipefail
for arch in amd64 arm64; do
GOARCH="$arch" go build \
-o "dist/wings_linux_${arch}" \
-v -trimpath \
-ldflags="-s -w -X github.com/Rene-Roscher/wings/system.Version=${VERSION}" \
github.com/Rene-Roscher/wings
chmod 755 "dist/wings_linux_${arch}"
done

# Catches a broken ldflags path silently producing a binary that reports
# "develop" — which would otherwise only surface on a node, after release.
- name: Assert the binary reports the version it was built with
env:
VERSION: ${{ steps.resolve.outputs.version }}
run: |
set -euo pipefail
reported="$(./dist/wings_linux_amd64 version | head -n1)"
echo "$reported"
printf '%s' "$reported" | grep -qF "wings v${VERSION}" || {
echo "::error::binary reports '${reported}', expected 'wings v${VERSION}'"
exit 1
}

- name: Generate SHA256SUMS
run: |
set -euo pipefail
cd dist
sha256sum wings_linux_amd64 wings_linux_arm64 > SHA256SUMS
cat SHA256SUMS

- name: Attach the assets to the release
if: inputs.release-tag != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
TAG: ${{ inputs.release-tag }}
run: |
set -euo pipefail
# --clobber so that re-running a failed run replaces partial uploads
# instead of failing on "asset already exists".
gh release upload "$TAG" \
dist/wings_linux_amd64 \
dist/wings_linux_arm64 \
dist/SHA256SUMS \
--clobber

- name: Upload the binaries as run artifacts
if: inputs.release-tag == ''
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: wings-binaries
path: dist/
101 changes: 67 additions & 34 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
@@ -1,25 +1,77 @@
name: Docker

# Called by release.yaml in the same run (a release published with
# GITHUB_TOKEN does not trigger `on: release`, so the old
# `on: release: published` listener would never fire once publishing is
# automated), and on its own for `:develop` images.
#
# Tag meanings:
# :1.13.2, :v1.13.2 — a published GitHub Release
# :latest — the newest published GitHub Release
# :develop — the newest push to develop
#
# This workflow deliberately does NOT push :latest. It is moved by release.yaml's
# publish job, by digest, only after the binaries, the image and the release
# assets have all been verified — otherwise a failure in any later job would
# leave :latest pointing at a build that never became a release.

on:
workflow_call:
inputs:
ref:
description: Commit SHA (or ref) to build. Defaults to the caller's ref.
type: string
required: false
default: ''
version:
description: >-
Release version without a leading `v` (e.g. 1.13.2). When set, the
image is tagged as a release build.
type: string
required: false
default: ''
outputs:
digest:
description: Digest of the pushed image, for retagging by the caller.
value: ${{ jobs.build.outputs.digest }}
push:
branches:
- develop
release:
types:
- published

permissions:
contents: read
packages: write

concurrency:
group: docker-${{ inputs.version || github.ref }}
cancel-in-progress: false

jobs:
build-and-push:
build:
name: Build and Push
runs-on: ubuntu-24.04
# Always run against a tag, even if the commit into the tag has [docker skip] within the commit message.
if: "!contains(github.ref, 'develop') || (!contains(github.event.head_commit.message, 'skip docker') && !contains(github.event.head_commit.message, 'docker skip'))"
permissions:
contents: read
packages: write
# `skip docker` only applies to the develop path. A release build must never
# be skippable by a commit message, or publish would fail with no digest.
if: "inputs.version != '' || (!contains(github.event.head_commit.message, 'skip docker') && !contains(github.event.head_commit.message, 'docker skip'))"
outputs:
digest: ${{ steps.build.outputs.digest }}
steps:
- name: Code checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: ${{ inputs.ref }}

- name: Get build information
id: build_info
env:
VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
if [ -n "$VERSION" ]; then
echo "build_version=${VERSION}" >> "$GITHUB_OUTPUT"
else
echo "build_version=dev-$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
fi

- name: Docker metadata
id: docker_meta
Expand All @@ -29,9 +81,9 @@ jobs:
flavor: |
latest=false
tags: |
type=raw,value=latest,enable=${{ github.event_name == 'release' && github.event.action == 'published' && github.event.release.prerelease == false }}
type=ref,event=tag
type=ref,event=branch
type=raw,value=${{ inputs.version }},enable=${{ inputs.version != '' }}
type=raw,value=v${{ inputs.version }},enable=${{ inputs.version != '' }}
type=ref,event=branch,enable=${{ inputs.version == '' }}

- name: Setup QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
Expand All @@ -46,35 +98,16 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Get Build Information
id: build_info
run: |
echo "version_tag=${GITHUB_REF/refs\/tags\/v/}" >> "$GITHUB_OUTPUT"
echo "short_sha=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"

- name: Build and Push (tag)
- name: Build and push
id: build
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
if: "github.event_name == 'release' && github.event.action == 'published'"
with:
context: .
file: ./Dockerfile
push: true
platforms: linux/amd64,linux/arm64
build-args: |
VERSION=${{ steps.build_info.outputs.version_tag }}
labels: ${{ steps.docker_meta.outputs.labels }}
tags: ${{ steps.docker_meta.outputs.tags }}

- name: Build and Push (develop)
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
if: "github.event_name == 'push' && contains(github.ref, 'develop')"
with:
context: .
file: ./Dockerfile
push: ${{ github.event_name != 'pull_request' }}
platforms: linux/amd64,linux/arm64
build-args: |
VERSION=dev-${{ steps.build_info.outputs.short_sha }}
VERSION=${{ steps.build_info.outputs.build_version }}
labels: ${{ steps.docker_meta.outputs.labels }}
tags: ${{ steps.docker_meta.outputs.tags }}
cache-from: type=gha
Expand Down
Loading