Skip to content

Release

Release #5

Workflow file for this run

name: Release
on:
push:
tags: ["v*"]
workflow_dispatch: {}
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: read
env:
GO_VERSION: "1.26"
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
release:
name: Release
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
timeout-minutes: 30
environment: release
permissions:
contents: write
packages: write
id-token: write
outputs:
hashes: ${{ steps.hash.outputs.hashes }}
digest: ${{ steps.build.outputs.digest }}
steps:
- uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: Login to GHCR
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Docker Hub
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
- name: Capture build date
id: build_date
run: echo "date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT"
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89 # v7.2.2
with:
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Generate provenance subjects
id: hash
shell: bash -Eeuo pipefail {0}
run: |
echo "hashes=$(cat goreleaser-dist/checksums.txt | base64 -w0)" >> "$GITHUB_OUTPUT"
- name: Build and push multi-arch image
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
id: build
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
docker.io/attuneio/attune:${{ github.ref_name }}
docker.io/attuneio/attune:latest
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
DATE=${{ steps.build_date.outputs.date }}
labels: |
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.version=${{ github.ref_name }}
- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Sign GHCR image
shell: bash -Eeuo pipefail -x {0}
run: |
cosign sign --yes \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
- name: Sign Docker Hub image
shell: bash -Eeuo pipefail -x {0}
run: |
cosign sign --yes \
docker.io/attuneio/attune@${{ steps.build.outputs.digest }}
- name: Attest container image
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true
- name: Generate SBOM
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
format: spdx-json
output-file: sbom.spdx.json
- name: Trivy scan released image
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
severity: HIGH,CRITICAL
exit-code: 1
- name: Generate install manifest and CRDs bundle
shell: bash -Eeuo pipefail -x {0}
run: |
make build-installer IMG=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
make build-crds
- name: Attach install manifest, CRDs, and SBOM to release
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3
with:
files: |
dist/install.yaml
dist/crds.yaml
sbom.spdx.json
helm-release:
name: Helm Chart Release
runs-on: ubuntu-latest
timeout-minutes: 10
needs: [release]
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5
with:
version: v4.1.4
- name: Login to GHCR (Helm)
shell: bash -Eeuo pipefail -x {0}
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ${{ env.REGISTRY }} \
--username ${{ github.actor }} --password-stdin
- name: Login to GHCR (Docker/cosign)
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Package and push Helm chart
shell: bash -Eeuo pipefail -x {0}
run: |
# Update chart version to match tag
VERSION="${{ github.ref_name }}"
VERSION="${VERSION#v}" # Strip 'v' prefix
sed -i "s/^version:.*/version: ${VERSION}/" charts/attune/Chart.yaml
sed -i "s/^appVersion:.*/appVersion: ${VERSION}/" charts/attune/Chart.yaml
helm package charts/attune
helm push attune-${VERSION}.tgz oci://${{ env.REGISTRY }}/${{ github.repository_owner }}/charts
- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Sign Helm chart
shell: bash -Eeuo pipefail -x {0}
run: |
VERSION="${{ github.ref_name }}"
VERSION="${VERSION#v}"
cosign sign --yes \
${{ env.REGISTRY }}/${{ github.repository_owner }}/charts/attune:${VERSION}
# SLSA Level 3 provenance for GoReleaser binary artifacts.
# Runs as a reusable workflow (required for non-forgeable provenance).
provenance:
name: Binary Provenance
needs: [release]
permissions:
actions: read
id-token: write
contents: write
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0
with:
base64-subjects: "${{ needs.release.outputs.hashes }}"
upload-assets: true
# SLSA Level 3 provenance for the container image.
container-provenance:
name: Container Provenance
needs: [release]
permissions:
actions: read
id-token: write
packages: write
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0
with:
image: ghcr.io/${{ github.repository }}
digest: ${{ needs.release.outputs.digest }}
registry-username: ${{ github.actor }}
secrets:
registry-password: ${{ secrets.GITHUB_TOKEN }}
# Sync docker/README.md to the Docker Hub repository description.
dockerhub-readme:
name: Docker Hub README
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [release]
steps:
- uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Update Docker Hub description
uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
repository: attuneio/attune
readme-filepath: docker/README.md
short-description: "Safe, in-place Kubernetes pod resource right-sizing. VPA done right."