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
12 changes: 12 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.git
.github
.cursor
.direnv
.envrc
.env*
*.out
result
dist
scenarios
examples
docs
101 changes: 101 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: CI

on:
pull_request:
push:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
validate:
name: Validate Flake
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: cachix/install-nix-action@v31
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}

- name: Validate flake
run: nix flake check --no-build

check:
name: ${{ matrix.check }}
runs-on: ubuntu-latest
needs: [validate]
strategy:
fail-fast: false
matrix:
check: [tidy, lint, fmt, lint-md]
steps:
- uses: actions/checkout@v4

- uses: cachix/install-nix-action@v31
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}

- name: Run ${{ matrix.check }}
run: nix run .#${{ matrix.check }}

- name: Verify no uncommitted changes
if: matrix.check == 'tidy' || matrix.check == 'fmt'
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "::error::Run 'nix run .#${{ matrix.check }}' and commit changes"
git diff
exit 1
fi

unit-test:
name: Unit Tests
runs-on: ubuntu-latest
needs: [check]
steps:
- uses: actions/checkout@v4

- uses: cachix/install-nix-action@v31
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}

- name: Run unit tests with race detector
run: nix run .#test-unit

- name: Upload coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-unit
path: coverage-unit.out
retention-days: 1

report:
name: Coverage Report
runs-on: ubuntu-latest
needs: [unit-test]
if: always() && needs.unit-test.result == 'success'
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4

- name: Download unit test coverage
uses: actions/download-artifact@v4
with:
name: coverage-unit

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
use_oidc: true
fail_ci_if_error: true
files: ./coverage-unit.out
flags: unittests
name: deployah-unit
disable_search: true
103 changes: 103 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Release

on:
push:
branches: [main]
tags: ["v*"]

permissions:
contents: write
packages: write

jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: deployah/deployah
# 'latest' only on stable tags (no pre-release suffix like -alpha, -beta, -rc)
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=raw,value=latest,enable=${{ github.ref_type == 'tag' && !contains(github.ref_name, '-') }}
type=edge,branch=${{ github.event.repository.default_branch }}
flavor: |
latest=false

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
buildkitd-config-inline: |
[worker.oci]
max-parallelism = 10

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build artifacts
if: startsWith(github.ref, 'refs/tags/')
uses: docker/bake-action@v6
with:
targets: artifact
provenance: false

- name: Move artifacts
if: startsWith(github.ref, 'refs/tags/')
run: |
find ./dist -type f -not -name "SHA256SUMS" -exec mv {} ./dist/ \;
find ./dist -name "SHA256SUMS" -exec cat {} \; | sort -u > ./dist/SHA256SUMS.combined
mv ./dist/SHA256SUMS.combined ./dist/SHA256SUMS
find ./dist -type d -empty -delete

- name: Upload artifacts
if: startsWith(github.ref, 'refs/tags/')
uses: actions/upload-artifact@v4
with:
name: deployah-artifacts
path: ./dist/*
if-no-files-found: error

- name: Build and push image
uses: docker/bake-action@v6
with:
targets: image
push: true
sbom: true
provenance: true
files: |
./docker-bake.hcl
cwd://${{ steps.meta.outputs.bake-file }}

- name: Sync Docker Hub description
uses: peter-evans/dockerhub-description@v4
if: github.ref_name == github.event.repository.default_branch
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
short-description: ${{ github.event.repository.description }}

- name: GitHub Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
draft: true
generate_release_notes: true
files: |
dist/*.tar.gz
dist/*.zip
dist/*.sha256sum
dist/SHA256SUMS
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ go.work.sum
# Kind cluster config
.kubeconfig

# Docker Buildx artifact output
/dist

# Coverage profiles
coverage*.out
coverage*.html
Expand Down
50 changes: 50 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.6.1 AS xx

FROM --platform=$BUILDPLATFORM golang:1.26-alpine AS base
ENV GO111MODULE=on
ENV CGO_ENABLED=0
COPY --from=xx / /
RUN apk add --update --no-cache build-base coreutils git zip
WORKDIR /src

FROM base AS build
ARG TARGETPLATFORM
RUN --mount=type=bind,target=/src,rw \
--mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
xx-go build -trimpath -ldflags="-s -w" -o /usr/bin/deployah . \
&& xx-verify --static /usr/bin/deployah

FROM scratch AS binary
COPY --from=build /usr/bin/deployah /

FROM base AS releaser
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
WORKDIR /work
RUN --mount=from=binary,target=/build \
--mount=type=bind,target=/src \
mkdir -p /out \
&& cp /build/deployah README.md LICENSE . \
&& if [ "$TARGETOS" = "windows" ]; then \
zip -q "/out/deployah-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}.zip" \
deployah README.md LICENSE; \
else \
tar -czvf "/out/deployah-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}.tar.gz" \
deployah README.md LICENSE; \
fi \
&& cd /out \
&& sha256sum "deployah-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}."* \
> "deployah-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}.sha256sum" \
&& sha256sum "deployah-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}."* >> "SHA256SUMS"

FROM scratch AS artifact
COPY --from=releaser /out /

FROM alpine:3.22
RUN apk add --update --no-cache ca-certificates tzdata
COPY --from=binary /deployah /usr/bin/deployah
ENTRYPOINT ["deployah"]
CMD ["help"]
25 changes: 25 additions & 0 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Special target: https://github.com/docker/metadata-action#bake-definition
target "docker-metadata-action" {}

target "image" {
inherits = ["docker-metadata-action"]
platforms = [
"linux/amd64",
"linux/arm64",
"linux/arm/v7",
]
}

target "artifact" {
target = "artifact"
output = ["./dist"]
platforms = [
"linux/amd64",
"linux/arm64",
"linux/arm/v7",
"darwin/amd64",
"darwin/arm64",
"windows/amd64",
"windows/arm64",
]
}
Loading