name: Release Artifacts on: push: tags: - "*" workflow_dispatch: jobs: validate-tag: name: Validate release tag runs-on: ubuntu-latest outputs: tag: ${{ steps.meta.outputs.tag }} prerelease: ${{ steps.meta.outputs.prerelease }} steps: - name: Validate tag and determine prerelease flag id: meta shell: bash run: | set -eu tag="${{ gitea.ref_name }}" echo "tag=${tag}" >> "${GITHUB_OUTPUT}" # Allowed tags: # - Stable: 1.2.3 # - Prerelease: 1.2.3-alpha1 | 1.2.3-beta1 | 1.2.3-rc1 if [[ "${tag}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "prerelease=false" >> "${GITHUB_OUTPUT}" elif [[ "${tag}" =~ ^[0-9]+\.[0-9]+\.[0-9]+-(alpha|beta|rc)[0-9]+$ ]]; then echo "prerelease=true" >> "${GITHUB_OUTPUT}" else echo "Invalid tag format: ${tag}" echo "Expected one of:" echo " - 1.2.3" echo " - 1.2.3-alpha1" echo " - 1.2.3-beta1" echo " - 1.2.3-rc1" exit 1 fi build-and-release-executables: name: Build and release executables needs: validate-tag runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Go uses: actions/setup-go@v5 with: go-version-file: go.mod cache: true - name: Setup Node uses: actions/setup-node@v4 with: node-version: "20" cache: npm cache-dependency-path: web/ui/package-lock.json - name: Install UI deps run: npm --prefix ./web/ui ci - name: Build UI assets run: npm --prefix ./web/ui run build - name: Run tests run: make test - name: Run race tests run: make test-race - name: Build release binaries shell: bash run: | set -eu mkdir -p dist for arch in amd64 arm64; do base="scratchbox-linux-${arch}" CGO_ENABLED=0 GOOS=linux GOARCH="${arch}" \ go build -trimpath -ldflags "-s -w" \ -o "dist/${base}-default" ./cmd/scratchbox CGO_ENABLED=0 GOOS=linux GOARCH="${arch}" \ go build -trimpath -tags "netgo osusergo" -ldflags "-s -w" \ -o "dist/${base}-static" ./cmd/scratchbox file "dist/${base}-static" | grep -q "statically linked" done - name: Package release archives shell: bash run: | set -eu rm -rf release-packages mkdir -p release-packages for bin in dist/scratchbox-linux-*; do name="$(basename "${bin}")" archive="scratchbox-${{ needs.validate-tag.outputs.tag }}-${name#scratchbox-}.tar.gz" stage="release-packages/${name}" rm -rf "${stage}" mkdir -p "${stage}" cp README.md "${stage}/" cp "${bin}" "${stage}/" tar -C "${stage}" -czf "${archive}" . done - name: Generate release notes shell: bash run: | set -eu current_tag="${{ needs.validate-tag.outputs.tag }}" prev_tag="$(git tag --sort=-creatordate | awk -v cur="${current_tag}" '$0 != cur { print; exit }')" { echo "## Release ${current_tag}" echo if [ -n "${prev_tag}" ]; then echo "Changes since \`${prev_tag}\`:" echo git log --pretty='- %h %s' "${prev_tag}..${current_tag}" else echo "Changes in this release:" echo git log --pretty='- %h %s' "${current_tag}" fi echo echo "## Artifacts" echo echo "- \`linux-amd64-default\`" echo "- \`linux-amd64-static\`" echo "- \`linux-arm64-default\`" echo "- \`linux-arm64-static\`" } > RELEASE_NOTES.md - name: Create release and upload archives uses: https://gitea.com/actions/gitea-release-action@v1 with: tag_name: ${{ needs.validate-tag.outputs.tag }} name: ${{ needs.validate-tag.outputs.tag }} prerelease: ${{ needs.validate-tag.outputs.prerelease }} body_path: RELEASE_NOTES.md files: |- scratchbox-${{ needs.validate-tag.outputs.tag }}-linux-*.tar.gz build-and-release-docker-image: name: Build and release Docker image needs: [validate-tag, build-and-release-executables] runs-on: ubuntu-latest permissions: code: read packages: write steps: - name: Checkout uses: actions/checkout@v4 - name: Resolve registry and image names id: image shell: bash run: | set -eu host="${{ gitea.server_url }}" host="${host#http://}" host="${host#https://}" host="${host%%/*}" repo="$(printf '%s' "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]')" image="${host}/${repo}" echo "registry_host=${host}" >> "${GITHUB_OUTPUT}" echo "repository_lower=${repo}" >> "${GITHUB_OUTPUT}" echo "image=${image}" >> "${GITHUB_OUTPUT}" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to registry uses: docker/login-action@v3 with: registry: ${{ secrets.GIT_REGISTRY || steps.image.outputs.registry_host }} username: ${{ secrets.GIT_USER || gitea.actor }} password: ${{ secrets.GIT_PACKAGES_TOKEN || secrets.GITEA_TOKEN }} - name: Extract Docker metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ secrets.GIT_REGISTRY || steps.image.outputs.registry_host }}/${{ steps.image.outputs.repository_lower }} tags: | type=raw,value=${{ needs.validate-tag.outputs.tag }} type=raw,value=latest - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max