mirror of
https://github.com/cole-maxwell1/todo-hetzner.git
synced 2026-10-27 19:02:49 -05:00
Add PostgreSQL-backed Go validation for application changes and semantic-version release publishing to GHCR. Default deployments to the public image and prevent host setup from starting the application before deployment.
131 lines
4.0 KiB
YAML
131 lines
4.0 KiB
YAML
name: Publish container image
|
|
|
|
on:
|
|
release:
|
|
types: [published]
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
REGISTRY: ghcr.io
|
|
IMAGE_NAME: ${{ github.repository }}
|
|
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
|
|
jobs:
|
|
test:
|
|
name: Test release
|
|
runs-on: ubuntu-latest
|
|
services:
|
|
postgres:
|
|
image: postgres:17-alpine
|
|
env:
|
|
POSTGRES_DB: todo_test
|
|
POSTGRES_USER: todo_test
|
|
POSTGRES_PASSWORD: test-password
|
|
ports:
|
|
- 5432:5432
|
|
options: >-
|
|
--health-cmd "pg_isready -U todo_test -d todo_test"
|
|
--health-interval 10s
|
|
--health-timeout 5s
|
|
--health-retries 5
|
|
defaults:
|
|
run:
|
|
working-directory: app
|
|
env:
|
|
TEST_DATABASE_URL: postgres://todo_test:test-password@127.0.0.1:5432/todo_test?sslmode=disable
|
|
steps:
|
|
- name: Validate release tag
|
|
working-directory: .
|
|
run: |
|
|
if [[ ! "$RELEASE_TAG" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(\+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$ ]]; then
|
|
printf 'Release tag must use semantic versioning with a v prefix: %s\n' "$RELEASE_TAG" >&2
|
|
exit 1
|
|
fi
|
|
|
|
- name: Check out release
|
|
uses: actions/checkout@v6
|
|
with:
|
|
ref: ${{ env.RELEASE_TAG }}
|
|
|
|
- name: Set up Go
|
|
uses: actions/setup-go@v6
|
|
with:
|
|
go-version-file: app/go.mod
|
|
cache-dependency-path: app/go.sum
|
|
|
|
- name: Run tests
|
|
run: go test ./...
|
|
|
|
- name: Run vet
|
|
run: go vet ./...
|
|
|
|
publish:
|
|
name: Publish image
|
|
needs: test
|
|
runs-on: ubuntu-latest
|
|
concurrency:
|
|
group: publish-image-${{ github.event.release.tag_name }}
|
|
cancel-in-progress: false
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
attestations: write
|
|
id-token: write
|
|
steps:
|
|
- name: Check out release
|
|
uses: actions/checkout@v6
|
|
with:
|
|
ref: ${{ env.RELEASE_TAG }}
|
|
|
|
- name: Set up QEMU
|
|
uses: docker/setup-qemu-action@v3
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Log in to GHCR
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Generate image metadata
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
tags: |
|
|
type=semver,pattern={{raw}},value=${{ env.RELEASE_TAG }}
|
|
type=semver,pattern={{version}},value=${{ env.RELEASE_TAG }}
|
|
type=semver,pattern={{major}}.{{minor}},value=${{ env.RELEASE_TAG }}
|
|
type=semver,pattern={{major}},value=${{ env.RELEASE_TAG }},enable=${{ !startsWith(env.RELEASE_TAG, 'v0.') }}
|
|
type=raw,value=latest,enable=${{ !github.event.release.prerelease }}
|
|
labels: |
|
|
org.opencontainers.image.description=Server-rendered Go todo application deployed to Hetzner Cloud
|
|
annotations: |
|
|
org.opencontainers.image.description=Server-rendered Go todo application deployed to Hetzner Cloud
|
|
env:
|
|
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
|
|
|
|
- name: Build and push image
|
|
id: push
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: app
|
|
file: app/Dockerfile
|
|
platforms: linux/amd64,linux/arm64
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
annotations: ${{ steps.meta.outputs.annotations }}
|
|
|
|
- name: Attest image provenance
|
|
uses: actions/attest@v4
|
|
with:
|
|
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
subject-digest: ${{ steps.push.outputs.digest }}
|
|
push-to-registry: true
|