diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 21e61ac..9cb6231 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,54 +1,37 @@ name: Build on: - schedule: - - cron: "0 10 * * *" push: branches: - "main" - tags: - - "v*.*.*" pull_request: - branches: - - "main" jobs: build: runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Install devbox uses: jetify-com/devbox-install-action@v0.11.0 with: enable-cache: true - - - name: Login to GitHub Container Registry - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - ghcr.io/mentos1386/zdravko - tags: | - type=schedule - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha - - name: Setup Golang cache uses: actions/cache@v4 with: @@ -59,18 +42,13 @@ jobs: restore-keys: | ${{ runner.os }}-go- - - name: Build binaries - run: devbox run -- just build-bin + - name: Build artifacts + run: devbox run -- just unstable - - name: Build and push - uses: docker/build-push-action@v5 + - uses: actions/upload-artifact@v4 with: - file: build/Dockerfile - context: . - push: ${{ github.event_name != 'pull_request' }} - platforms: linux/amd64,linux/arm64 - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + name: Unstable Build + path: dist deploy: runs-on: ubuntu-latest diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..7b0b8cc --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,46 @@ +name: Release + +on: + push: + tags: + - "v*" + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Install devbox + uses: jetify-com/devbox-install-action@v0.11.0 + with: + enable-cache: true + - name: Setup Golang cache + uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Release + run: devbox run -- just release diff --git a/.gitignore b/.gitignore index 443e8fc..47215f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ bin/ +dist/ # Node node_modules/ diff --git a/README.md b/README.md index cde9efb..dd67300 100644 --- a/README.md +++ b/README.md @@ -48,10 +48,10 @@ just generate-jwt-key # Start development environment just run -# Or build binaries -just build-bin -# Or docker image (for current platform) -just build-docker +# Or build binaries, packages, docker images... +just build +# Or build only one binary. +just build-only-binary ``` ### License diff --git a/build/Dockerfile b/build/Dockerfile index a21fee6..3bc1e3b 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,9 +1,6 @@ FROM gcr.io/distroless/static-debian12:latest as production -ARG TARGETARCH -ARG TARGETOS - -COPY ./bin/zdravko-${TARGETOS}-${TARGETARCH} /bin/zdravko +COPY zdravko /bin/zdravko COPY LICENSE /LICENSE COPY README.md /README.md @@ -22,8 +19,5 @@ ENV TEMPORAL_DATABASE_PATH=/data/temporal.db ENV KEYVALUE_DATABASE_PATH=/data/keyvalue.db VOLUME /data -ENV DATABASE_PATH=/data/zdravko.db -ENV TEMPORAL_DATABASE_PATH=/data/temporal.db - ENTRYPOINT ["/bin/zdravko"] CMD ["--server", "--temporal", "--worker"] diff --git a/build/Justfile b/build/Justfile index 7b2f001..0a5aeec 100644 --- a/build/Justfile +++ b/build/Justfile @@ -1,22 +1,26 @@ -# Build the application -build: build-bin build-docker +# Only build binary for current platform. +build-only-bin: + goreleaser build --snapshot --clean --single-target --config ./build/release.yaml -# Build multiarch binaries -build-bin: - #!/bin/bash - for os in {{OS}} - do - for arch in {{ARCH}} - do - echo "Building zdravko for $os $arch..." - CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -o bin/zdravko-$os-$arch cmd/zdravko/main.go - done +# Build binaries, packages, docker images for all platforms. +build: + goreleaser release --snapshot --clean --config ./build/release.yaml + +# Unstable release process. +unstable: + #!/bin/env bash + set -exuo pipefail + goreleaser release --clean --snapshot --config ./build/release.yaml + + IMAGES=$(docker image ls --format "{{'{{ .Repository }}:{{ .Tag }}'}}" | grep -e "{{ DOCKER_IMAGE }}.*") + + for image in ${IMAGES}; do + docker push ${image} done -# Build docker image -build-docker: build-bin - #!/bin/bash - docker buildx build \ - -f build/Dockerfile \ - -t {{DOCKER_IMAGE}} \ - . + docker manifest create {{ DOCKER_IMAGE }} ${IMAGES} + docker manifest push {{ DOCKER_IMAGE }} + +# Stable release process. +release: + goreleaser release --clean --config ./build/release.yaml diff --git a/build/release.yaml b/build/release.yaml new file mode 100644 index 0000000..73ac742 --- /dev/null +++ b/build/release.yaml @@ -0,0 +1,100 @@ +report_sizes: true + +changelog: + use: github + +snapshot: + name_template: "{{ .Version }}-UNSTABLE-{{ .Branch }}-{{ .ShortCommit }}" + +builds: + - main: ./cmd/zdravko + mod_timestamp: "{{ .CommitTimestamp }}" + flags: + - -trimpath + goos: + - "darwin" + - "freebsd" + - "linux" + - "windows" + goarch: + - "amd64" + - "arm64" + +nfpms: + - vendor: Tine Jozelj + homepage: https://zdravko.mnts.dev + maintainer: Tine Jozelj + license: AGPL-3.0 + description: | + Zdravko is a selfhosted healthcheck service designed to work for small scale, + or multi region deployments. It can monitor virtually anything. + formats: + - apk + - deb + - rpm + - termux.deb + - archlinux + provides: + - zdravko + +universal_binaries: + - replace: true + +archives: + - format: tar.gz + wrap_in_directory: true + format_overrides: + - goos: windows + format: zip + +dockers: + - image_templates: + - "{{ .Env.DOCKER_REGISTRY }}:sha-{{ .ShortCommit }}-amd64" + - "{{ .Env.DOCKER_REGISTRY }}:{{ .Version }}-amd64" + - "{{ .Env.DOCKER_REGISTRY }}:latest-amd64" + use: buildx + goos: linux + goarch: amd64 + dockerfile: build/Dockerfile + extra_files: + - "README.md" + - "LICENSE" + build_flag_templates: + - "--pull" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--platform=linux/amd64" + - image_templates: + - "{{ .Env.DOCKER_REGISTRY }}:sha-{{ .ShortCommit }}-arm64" + - "{{ .Env.DOCKER_REGISTRY }}:{{ .Version }}-arm64" + - "{{ .Env.DOCKER_REGISTRY }}:latest-arm64" + use: buildx + goos: linux + goarch: arm64 + dockerfile: build/Dockerfile + extra_files: + - "README.md" + - "LICENSE" + build_flag_templates: + - "--pull" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--platform=linux/arm64" + +docker_manifests: + - name_template: "{{ .Env.DOCKER_REGISTRY }}:sha-{{ .ShortCommit }}" + image_templates: + - "{{ .Env.DOCKER_REGISTRY }}:{{ .Version }}-amd64" + - "{{ .Env.DOCKER_REGISTRY }}:{{ .Version }}-arm64" + - name_template: "{{ .Env.DOCKER_REGISTRY }}:{{ .Version }}" + image_templates: + - "{{ .Env.DOCKER_REGISTRY }}:{{ .Version }}-amd64" + - "{{ .Env.DOCKER_REGISTRY }}:{{ .Version }}-arm64" + - name_template: "{{ .Env.DOCKER_REGISTRY }}:latest" + image_templates: + - "{{ .Env.DOCKER_REGISTRY }}:{{ .Version }}-amd64" + - "{{ .Env.DOCKER_REGISTRY }}:{{ .Version }}-arm64" diff --git a/cmd/zdravko/main.go b/cmd/zdravko/main.go index 9bd8ee0..71ca43a 100644 --- a/cmd/zdravko/main.go +++ b/cmd/zdravko/main.go @@ -14,6 +14,12 @@ import ( "github.com/mentos1386/zdravko/pkg/worker" ) +var ( + version = "dev" + commit = "none" + date = "unknown" +) + type StartableAndStoppable interface { Name() string Start() error @@ -42,7 +48,8 @@ func main() { flag.BoolVar(&startTemporal, "temporal", false, "Start the temporal") flag.Parse() - slog.Info("Starting zdravko...", "server", startServer, "worker", startWorker, "temporal", startTemporal) + slog.Info("Starting zdravko", "version", version, "commit", commit, "date", date) + slog.Info("Components...", "server", startServer, "worker", startWorker, "temporal", startTemporal) if !startServer && !startWorker && !startTemporal { slog.Error("At least one of the following must be set: --server, --worker, --temporal") diff --git a/deploy/Justfile b/deploy/Justfile index 23a74f3..3d149c5 100644 --- a/deploy/Justfile +++ b/deploy/Justfile @@ -12,5 +12,5 @@ deploy-fly-set-jwt-key-secrets: EOF # Deploy locally with docker compose -deploy-docker: build-docker +deploy-docker: build docker compose --file dpeloy/docker-compose.yaml up diff --git a/devbox.json b/devbox.json index a5375cb..e3a0bc0 100644 --- a/devbox.json +++ b/devbox.json @@ -8,6 +8,7 @@ "sqlite-web@latest", "go@1.22", "tailwindcss@latest", - "temporal-cli@latest" + "temporal-cli@latest", + "goreleaser@latest" ] } diff --git a/devbox.lock b/devbox.lock index 8cf74bf..9b17924 100644 --- a/devbox.lock +++ b/devbox.lock @@ -69,6 +69,54 @@ } } }, + "goreleaser@latest": { + "last_modified": "2024-05-29T10:04:41Z", + "resolved": "github:NixOS/nixpkgs/ac82a513e55582291805d6f09d35b6d8b60637a1#goreleaser", + "source": "devbox-search", + "version": "1.26.2", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/3igms7180pkaki16zvfid4q7jp2g22b0-goreleaser-1.26.2", + "default": true + } + ], + "store_path": "/nix/store/3igms7180pkaki16zvfid4q7jp2g22b0-goreleaser-1.26.2" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/k5cnmyfha51wygjalza3kf6kjwwds0lh-goreleaser-1.26.2", + "default": true + } + ], + "store_path": "/nix/store/k5cnmyfha51wygjalza3kf6kjwwds0lh-goreleaser-1.26.2" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/9xx7jd8hi5ff305kysnq7wylf92w69vh-goreleaser-1.26.2", + "default": true + } + ], + "store_path": "/nix/store/9xx7jd8hi5ff305kysnq7wylf92w69vh-goreleaser-1.26.2" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/lwgrhyjg21q6zd1akid2v1nxxnpsscz1-goreleaser-1.26.2", + "default": true + } + ], + "store_path": "/nix/store/lwgrhyjg21q6zd1akid2v1nxxnpsscz1-goreleaser-1.26.2" + } + } + }, "just@latest": { "last_modified": "2024-01-27T14:55:31Z", "resolved": "github:NixOS/nixpkgs/160b762eda6d139ac10ae081f8f78d640dd523eb#just", diff --git a/justfile b/justfile index 7304cc5..2f71c39 100644 --- a/justfile +++ b/justfile @@ -8,6 +8,9 @@ export JWT_PRIVATE_KEY := `cat jwt.private.pem || echo ""` export JWT_PUBLIC_KEY := `cat jwt.public.pem || echo ""` GIT_SHA := `git rev-parse --short HEAD` + +export DOCKER_REGISTRY := "ghcr.io/mentos1386/zdravko" + DOCKER_IMAGE := "ghcr.io/mentos1386/zdravko:sha-"+GIT_SHA STATIC_DIR := "./web/static" @@ -52,7 +55,7 @@ generate-jwt-key: openssl rsa -pubout -in jwt.private.pem -out jwt.public.pem # Run Docker application. -run-docker: build-docker +run-docker: build docker run -p 8080:8080 \ -it --rm \ -e SESSION_SECRET \