Build and publish / Test and build (darwin) (push) Successful in 1m25s
Build and publish / Test and build (windows) (push) Successful in 3m6s
Build and publish / Test and build (linux) (push) Successful in 3m59s
Build and publish / Build and publish Docker image (push) Successful in 2m41s
The workflow now verifies that all three DinD TLS certificates are readable before attempting registry login or Buildx operations. The check fails early with instructions to apply runner-compose.yaml if the runner has not mounted /certs/client into job containers. Buildx now creates a named Docker context from the TLS environment variables, as Buildx cannot use TLS endpoints without an explicit context. Each CI run uses a uniquely named builder (based
219 lines
8.0 KiB
YAML
219 lines
8.0 KiB
YAML
name: Build and publish
|
|
|
|
on:
|
|
push:
|
|
branches: ['**']
|
|
tags: ['v*']
|
|
pull_request:
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
CGO_ENABLED: '0'
|
|
# CI uses the mock Ombi; never inherit a runner's live instance config.
|
|
OMBI_URL: ''
|
|
|
|
jobs:
|
|
binaries:
|
|
name: Test and build (${{ matrix.goos }})
|
|
runs-on: ${{ matrix.runner }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: macos
|
|
goos: darwin
|
|
- runner: ubuntu-latest
|
|
goos: linux
|
|
- runner: windows
|
|
goos: windows
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
steps:
|
|
- name: Checkout (macOS/Linux)
|
|
if: matrix.goos != 'windows'
|
|
uses: https://github.com/actions/checkout@v4
|
|
with:
|
|
persist-credentials: false
|
|
# The Windows self-hosted runner fails while starting the Node-based
|
|
# checkout action. The repository is public, so use Git directly there.
|
|
- name: Checkout (Windows)
|
|
if: matrix.goos == 'windows'
|
|
env:
|
|
GIT_SERVER_URL: ${{ gitea.server_url }}
|
|
GIT_REPOSITORY: ${{ gitea.repository }}
|
|
GIT_SHA: ${{ gitea.sha }}
|
|
run: |
|
|
git init .
|
|
git config core.autocrlf false
|
|
git remote add origin "${GIT_SERVER_URL}/${GIT_REPOSITORY}.git"
|
|
git fetch --depth=1 origin "$GIT_SHA"
|
|
git checkout --detach FETCH_HEAD
|
|
- uses: https://github.com/actions/setup-go@v5
|
|
with:
|
|
go-version-file: go.mod
|
|
cache: false
|
|
- name: Check formatting
|
|
run: |
|
|
files=$(gofmt -l .)
|
|
if [ -n "$files" ]; then
|
|
printf 'Run gofmt on:\n%s\n' "$files"
|
|
exit 1
|
|
fi
|
|
- name: Vet
|
|
run: go vet ./...
|
|
- name: Unit tests
|
|
run: go test ./...
|
|
- name: Mock integration tests
|
|
if: matrix.goos == 'linux'
|
|
run: go test -tags integration ./internal/integration_test/
|
|
- name: Build and package
|
|
env:
|
|
GOOS: ${{ matrix.goos }}
|
|
run: |
|
|
for arch in amd64 arm64; do
|
|
package="ombi-mcp-${GOOS}-${arch}"
|
|
binary=ombi-mcp
|
|
if [ "$GOOS" = windows ]; then binary=ombi-mcp.exe; fi
|
|
mkdir -p "dist/$package"
|
|
GOARCH="$arch" go build -trimpath -ldflags='-s -w' -o "dist/$package/$binary" ./cmd/ombi-mcp
|
|
cp README.md "dist/$package/"
|
|
tar -czf "dist/$package.tar.gz" -C dist "$package"
|
|
done
|
|
# v3 uses the artifact API supported by older Gitea installations too.
|
|
- uses: https://github.com/actions/upload-artifact@v3
|
|
with:
|
|
name: ombi-mcp-${{ matrix.goos }}
|
|
path: dist/*.tar.gz
|
|
if-no-files-found: error
|
|
|
|
docker:
|
|
name: Build and publish Docker image
|
|
needs: binaries
|
|
runs-on: ubuntu-latest
|
|
container:
|
|
options: >-
|
|
--volume /certs/client:/certs/client:ro
|
|
--add-host=docker:host-gateway
|
|
env:
|
|
DOCKER_CONFIG: /tmp/ombi-mcp-docker-config
|
|
# The act_runner service's environment is not inherited by job
|
|
# containers, so explicitly target the sibling Docker-in-Docker service.
|
|
DOCKER_HOST: tcp://docker:2376
|
|
DOCKER_TLS_VERIFY: '1'
|
|
DOCKER_CERT_PATH: /certs/client
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
steps:
|
|
- name: Verify Docker daemon access
|
|
run: |
|
|
for certificate in ca.pem cert.pem key.pem; do
|
|
if [ ! -r "$DOCKER_CERT_PATH/$certificate" ] || [ ! -s "$DOCKER_CERT_PATH/$certificate" ]; then
|
|
echo "Missing Docker TLS file: $DOCKER_CERT_PATH/$certificate" >&2
|
|
echo 'The runner must allow /certs/client in container.valid_volumes.' >&2
|
|
echo 'Apply docs/runner-compose.yaml to the existing runner Compose project.' >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
docker version
|
|
- uses: https://github.com/actions/checkout@v4
|
|
with:
|
|
persist-credentials: false
|
|
- name: Image metadata
|
|
id: image
|
|
env:
|
|
REPOSITORY: ${{ gitea.repository }}
|
|
COMMIT_SHA: ${{ gitea.sha }}
|
|
REF: ${{ gitea.ref }}
|
|
EVENT_NAME: ${{ gitea.event_name }}
|
|
DEFAULT_BRANCH: ${{ gitea.event.repository.default_branch }}
|
|
run: |
|
|
image="git.i3omb.com/$(printf '%s' "$REPOSITORY" | tr '[:upper:]' '[:lower:]')"
|
|
publish=false
|
|
tags="$image:sha-$COMMIT_SHA"
|
|
if [ "$EVENT_NAME" = push ]; then
|
|
if [ "$REF" = "refs/heads/$DEFAULT_BRANCH" ]; then
|
|
publish=true
|
|
tags="$tags,$image:latest"
|
|
elif [[ "$REF" == refs/tags/v* ]]; then
|
|
tag="${REF#refs/tags/}"
|
|
if [[ ! "$tag" =~ ^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$ ]]; then
|
|
echo 'Version tag is not a valid Docker tag'
|
|
exit 1
|
|
fi
|
|
publish=true
|
|
tags="$tags,$image:$tag"
|
|
fi
|
|
fi
|
|
echo "publish=$publish" >> "$GITHUB_OUTPUT"
|
|
echo "tags=$tags" >> "$GITHUB_OUTPUT"
|
|
echo "go_version=$(awk '$1 == "go" { print $2 }' go.mod)" >> "$GITHUB_OUTPUT"
|
|
- name: Log in to Gitea registry
|
|
if: steps.image.outputs.publish == 'true'
|
|
env:
|
|
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
|
run: |
|
|
printf '%s' "$REGISTRY_TOKEN" | docker login git.i3omb.com \
|
|
--username "$REGISTRY_USERNAME" --password-stdin
|
|
- name: Install Docker Buildx when unavailable
|
|
env:
|
|
BUILDX_VERSION: v0.16.2
|
|
run: |
|
|
if ! docker buildx version >/dev/null 2>&1; then
|
|
mkdir -p "$DOCKER_CONFIG/cli-plugins"
|
|
case "$(uname -m)" in
|
|
x86_64) buildx_arch=amd64 ;;
|
|
aarch64|arm64) buildx_arch=arm64 ;;
|
|
*) echo "Unsupported runner architecture: $(uname -m)" >&2; exit 1 ;;
|
|
esac
|
|
curl -fsSL \
|
|
"https://github.com/docker/buildx/releases/download/${BUILDX_VERSION}/buildx-${BUILDX_VERSION}.linux-${buildx_arch}" \
|
|
-o "$DOCKER_CONFIG/cli-plugins/docker-buildx"
|
|
chmod +x "$DOCKER_CONFIG/cli-plugins/docker-buildx"
|
|
fi
|
|
docker buildx version
|
|
- name: Build image with Docker Buildx
|
|
env:
|
|
IMAGE_TAGS: ${{ steps.image.outputs.tags }}
|
|
PUBLISH: ${{ steps.image.outputs.publish }}
|
|
GO_VERSION: ${{ steps.image.outputs.go_version }}
|
|
SOURCE_LABEL: ${{ gitea.server_url }}/${{ gitea.repository }}
|
|
REVISION_LABEL: ${{ gitea.sha }}
|
|
CI_RUN_ID: ${{ gitea.run_id }}
|
|
CI_RUN_ATTEMPT: ${{ gitea.run_attempt }}
|
|
run: |
|
|
docker buildx version
|
|
# Buildx requires a named context when the Docker endpoint uses TLS.
|
|
docker context create ombi-mcp-dind --docker \
|
|
"host=$DOCKER_HOST,ca=$DOCKER_CERT_PATH/ca.pem,cert=$DOCKER_CERT_PATH/cert.pem,key=$DOCKER_CERT_PATH/key.pem"
|
|
builder_name="ombi-mcp-${CI_RUN_ID}-${CI_RUN_ATTEMPT:-1}"
|
|
docker buildx create --name "$builder_name" --driver docker-container --use ombi-mcp-dind
|
|
trap 'docker buildx rm --force "$builder_name" >/dev/null 2>&1 || true' EXIT
|
|
docker buildx inspect "$builder_name" --bootstrap
|
|
|
|
tag_args=()
|
|
IFS=',' read -ra tags <<< "$IMAGE_TAGS"
|
|
for tag in "${tags[@]}"; do
|
|
tag_args+=(--tag "$tag")
|
|
done
|
|
|
|
push_args=()
|
|
if [ "$PUBLISH" = true ]; then
|
|
push_args+=(--push)
|
|
else
|
|
# Validate pull-request and branch builds without exporting an image.
|
|
push_args+=(--output=type=cacheonly)
|
|
fi
|
|
|
|
docker buildx build \
|
|
--builder "$builder_name" \
|
|
--platform linux/amd64,linux/arm64 \
|
|
--build-arg "GO_VERSION=$GO_VERSION" \
|
|
--label "org.opencontainers.image.source=$SOURCE_LABEL" \
|
|
--label "org.opencontainers.image.revision=$REVISION_LABEL" \
|
|
"${tag_args[@]}" \
|
|
"${push_args[@]}" \
|
|
.
|