Publish Container Images #1160
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Publish Container Images | |
# This workflow uses actions that are not certified by GitHub. | |
# They are provided by a third-party and are governed by | |
# separate terms of service, privacy policy, and support | |
# documentation. | |
on: | |
schedule: | |
- cron: "43 9 * * *" | |
push: | |
branches: [main] | |
# Publish semver tags as releases. | |
tags: ["v*.*.*"] | |
env: | |
# Use docker.io for Docker Hub if empty | |
REGISTRY: ghcr.io | |
# github.repository as <account>/<repo> | |
IMAGE_NAME: ${{ github.repository }} | |
RELEASE: ${{ github.ref_name }} | |
jobs: | |
debug-event: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Print workflow actor | |
run: echo "${{ toJSON(github.actor) }}" | |
- name: Print workflow event | |
run: jq '.' $GITHUB_EVENT_PATH | |
build-operator: | |
name: Build operator binaries | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
# This is used to complete the identity challenge | |
# with sigstore/fulcio when running outside of PRs. | |
id-token: write | |
strategy: | |
matrix: | |
os: [linux] | |
arch: [amd64, arm64, arm] | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Import environment variables from file | |
run: cat ".github/env" >> $GITHUB_ENV | |
- uses: actions/setup-go@v4 | |
with: | |
go-version: "${{ env.golang-version }}" | |
cache: true | |
# Install the cosign tool except on PR | |
# https://github.com/sigstore/cosign-installer | |
- name: Install cosign | |
uses: sigstore/cosign-installer@v3 | |
# Login against a Docker registry except on PR | |
# https://github.com/docker/login-action | |
- name: Log into registry ${{ env.REGISTRY }} | |
uses: docker/login-action@v2 | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
# Extract metadata (tags, labels) for Docker | |
# https://github.com/docker/metadata-action | |
- name: Extract Docker metadata | |
id: meta | |
uses: docker/metadata-action@v4 | |
with: | |
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
tags: | | |
type=schedule,pattern=main | |
type=ref,event=branch | |
type=ref,event=tag | |
type=ref,event=pr | |
flavor: | | |
suffix=-${{ matrix.arch }},onlatest=true | |
# Extract metadata (tags, labels) for Docker | |
# https://github.com/docker/metadata-action | |
- name: Extract Docker metadata (without suffixes) | |
id: meta_clean | |
uses: docker/metadata-action@v4 | |
with: | |
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
tags: | | |
type=schedule,pattern=main | |
type=ref,event=branch | |
type=ref,event=tag | |
type=ref,event=pr | |
- name: Build binaries | |
run: VERSION=${{ steps.meta_clean.outputs.version }} TARGET_OS=${{ matrix.os }} TARGET_ARCH=${{ matrix.arch }} make build | |
# Build and push Docker image with Buildx | |
# https://github.com/docker/build-push-action | |
- name: Build and push operator image | |
id: build-and-push-operator | |
uses: docker/build-push-action@v4 | |
with: | |
context: . | |
platforms: ${{ matrix.os }}/${{ matrix.arch }} | |
push: true | |
labels: ${{ steps.meta.outputs.labels }} | |
tags: ${{ steps.meta.outputs.tags }} | |
- name: Scan Image | |
uses: mondoohq/actions/docker-image@main | |
env: | |
MONDOO_CONFIG_BASE64: ${{ secrets.MONDOO_CLIENT }} | |
with: | |
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push-operator.outputs.digest }} | |
# Sign the resulting Docker image digest except on PRs. | |
# This will only write to the public Rekor transparency log when the Docker | |
# repository is public to avoid leaking data. If you would like to publish | |
# transparency data even for private images, pass --force to cosign below. | |
# https://github.com/sigstore/cosign | |
- name: Sign the published Docker image | |
# This step uses the identity token to provision an ephemeral certificate | |
# against the sigstore community Fulcio instance. | |
run: cosign sign -y ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push-operator.outputs.digest }} | |
push-virtual-tag: | |
name: Push multi-platform virtual tag | |
runs-on: ubuntu-latest | |
needs: | |
- build-operator | |
permissions: | |
contents: read | |
packages: write | |
# This is used to complete the identity challenge | |
# with sigstore/fulcio when running outside of PRs. | |
id-token: write | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
# Install the cosign tool except on PR | |
# https://github.com/sigstore/cosign-installer | |
- name: Install cosign | |
uses: sigstore/cosign-installer@v3 | |
# Login against a Docker registry except on PR | |
# https://github.com/docker/login-action | |
- name: Log into registry ${{ env.REGISTRY }} | |
uses: docker/login-action@v2 | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
# Extract metadata (tags, labels) for Docker | |
# https://github.com/docker/metadata-action | |
- name: Extract Docker metadata | |
id: meta | |
uses: docker/metadata-action@v4 | |
with: | |
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
- name: Push multi-platform virtual tag and sign | |
run: bash scripts/push-virtual-tag.sh | |
env: | |
TAGS: ${{ steps.meta.outputs.tags }} | |
CPU_ARCHS: amd64 arm64 arm | |
build-bundle: | |
if: startsWith(github.ref, 'refs/tags/v') | |
needs: | |
- push-virtual-tag | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
# This is used to complete the identity challenge | |
# with sigstore/fulcio when running outside of PRs. | |
id-token: write | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Import environment variables from file | |
run: cat ".github/env" >> $GITHUB_ENV | |
- name: Install Go | |
uses: actions/setup-go@v4 | |
with: | |
go-version: "${{ env.golang-version }}" | |
# Install the cosign tool except on PR | |
# https://github.com/sigstore/cosign-installer | |
- name: Install cosign | |
uses: sigstore/cosign-installer@v3 | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v2 | |
with: | |
image: tonistiigi/binfmt:latest | |
platforms: amd64,arm | |
# Workaround: https://github.com/docker/build-push-action/issues/461 | |
- name: Setup Docker buildx | |
uses: docker/setup-buildx-action@v2 | |
# Login against a Docker registry except on PR | |
# https://github.com/docker/login-action | |
- name: Log into registry ${{ env.REGISTRY }} | |
uses: docker/login-action@v2 | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Make bundle | |
id: make-bundle | |
run: | | |
export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac) | |
export OS=$(uname | awk '{print tolower($0)}') | |
export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/${{ env.operator-sdk-version }} | |
curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH} | |
gpg --keyserver keyserver.ubuntu.com --recv-keys 052996E2A20B5C7E | |
curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt | |
curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt.asc | |
gpg -u "Operator SDK (release) <[email protected]>" --verify checksums.txt.asc | |
grep operator-sdk_${OS}_${ARCH} checksums.txt | sha256sum -c - | |
chmod +x operator-sdk_${OS}_${ARCH} && sudo mv operator-sdk_${OS}_${ARCH} /usr/local/bin/operator-sdk | |
make bundle IMG='${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE }}' VERSION='${{ env.RELEASE }}' | |
# Extract metadata (tags, labels) for Docker | |
# https://github.com/docker/metadata-action | |
- name: Extract Docker metadata | |
id: meta-bundle | |
uses: docker/metadata-action@v4 | |
with: | |
images: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-bundle" | |
# Build and push Docker image bundle with Buildx | |
- name: Build and push bundle image | |
id: build-and-push-bundle | |
uses: docker/build-push-action@v4 | |
with: | |
context: . | |
file: bundle.Dockerfile | |
platforms: linux/amd64,linux/arm/v7,linux/arm64 | |
push: true | |
labels: ${{ steps.meta-bundle.outputs.labels }} | |
tags: ${{ steps.meta-bundle.outputs.tags }} | |
# Sign the resulting Docker image digest except on PRs. | |
# This will only write to the public Rekor transparency log when the Docker | |
# repository is public to avoid leaking data. If you would like to publish | |
# transparency data even for private images, pass --force to cosign below. | |
# https://github.com/sigstore/cosign | |
- name: Sign the published Docker image | |
# This step uses the identity token to provision an ephemeral certificate | |
# against the sigstore community Fulcio instance. | |
run: cosign sign -y ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-bundle@${{ steps.build-and-push-bundle.outputs.digest }} | |
# run olm e2e tests | |
run-olm-e2e: | |
name: OLM integration tests | |
if: startsWith(github.ref, 'refs/tags/v') | |
needs: | |
- build-bundle | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
k8s-version: [v1.24.16, v1.25.12, v1.26.7, v1.27.4] | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 # fetch is needed for "git tag --list" in the Makefile | |
- name: Import environment variables from file | |
run: cat ".github/env" >> $GITHUB_ENV | |
- name: Install Go | |
uses: actions/setup-go@v4 | |
with: | |
go-version: "${{ env.golang-version }}" | |
- name: Start minikube | |
uses: medyagh/setup-minikube@master | |
with: | |
memory: 4000m | |
kubernetes-version: ${{ matrix.k8s-version }} | |
- name: Install operator-sdk | |
id: operator-sdk | |
run: | | |
export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac) | |
export OS=$(uname | awk '{print tolower($0)}') | |
export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/${{ env.operator-sdk-version }} | |
curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH} | |
gpg --keyserver keyserver.ubuntu.com --recv-keys 052996E2A20B5C7E | |
curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt | |
curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt.asc | |
gpg -u "Operator SDK (release) <[email protected]>" --verify checksums.txt.asc | |
grep operator-sdk_${OS}_${ARCH} checksums.txt | sha256sum -c - | |
chmod +x operator-sdk_${OS}_${ARCH} && sudo mv operator-sdk_${OS}_${ARCH} /usr/local/bin/operator-sdk | |
# Now that dependencies are cached the tests start almost immediately after minikube has started | |
# this makes tests fail occasionally. This sleep gives the runner some time to become more stable | |
# before the test execution starts. | |
- name: Wait a bit for the runner to become more stable | |
run: kubectl -n kube-system wait --for=condition=Ready pods --all --timeout=60s | |
- name: Install Mondoo operator using OLM | |
run: | | |
operator-sdk olm install | |
kubectl -n olm wait --for=condition=Ready pods --all --timeout=60s | |
kubectl create ns mondoo-operator | |
operator-sdk run bundle ghcr.io/${{ github.repository }}-bundle:${{ github.ref_name }} --namespace mondoo-operator --timeout 3m0s | |
- name: Gather running pods | |
if: failure() | |
run: | | |
kubectl get pods -A | |
mkdir -p tests/integration/_output | |
kubectl get pods -n mondoo-operator -o yaml >> tests/integration/_output/mondoo-pods.log | |
kubectl logs -n olm deployment/olm-operator >> tests/integration/_output/olm-operator-pods.log | |
- name: Store creds | |
run: echo ${{ secrets.MONDOO_CLIENT }} | base64 -d > creds.json | |
- name: Extract Docker metadata | |
id: meta | |
uses: docker/metadata-action@v4 | |
with: | |
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
- name: Run integration tests | |
env: | |
MONDOO_SERVICE_ACCOUNT_EDGE: ${{ secrets.MONDOO_SERVICE_ACCOUNT_EDGE }} | |
run: EXTERNAL_INSTALLATION=1 VERSION=${{ steps.meta.outputs.version }} make test/integration/ci | |
- name: Clean up | |
run: | | |
operator-sdk cleanup mondoo-operator --namespace mondoo-operator | |
operator-sdk olm uninstall | |
- name: Upload test logs artifact | |
uses: actions/upload-artifact@v3 | |
if: failure() | |
with: | |
name: olm-test-logs-${{ matrix.k8s-version }} | |
path: /home/runner/work/mondoo-operator/mondoo-operator/tests/integration/_output/ | |
- uses: dorny/test-reporter@v1 | |
if: failure() || success() | |
with: | |
name: Report OLM test results | |
path: '*.xml' # Path to test results | |
reporter: java-junit # Format of test results | |
# publish kubectl manifests | |
run-release-manifests: | |
if: startsWith(github.ref, 'refs/tags/v') | |
uses: ./.github/workflows/release-manifests.yaml | |
needs: | |
- push-virtual-tag | |
# this should ensure the manifest is tagged latest, which is required for the install automation | |
- release-helm | |
# publish helm chart after the release of container images is complete | |
run-helm-tests: | |
name: Run helm integration tests | |
if: startsWith(github.ref, 'refs/tags/v') | |
needs: | |
- push-virtual-tag | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
checks: write | |
statuses: write | |
strategy: | |
fail-fast: false | |
matrix: | |
k8s-version: [v1.24.16, v1.25.12, v1.26.7, v1.27.4] | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Import environment variables from file | |
run: cat ".github/env" >> $GITHUB_ENV | |
- name: Install Go | |
uses: actions/setup-go@v4 | |
with: | |
go-version: "${{ env.golang-version }}" | |
- name: Start minikube | |
uses: medyagh/setup-minikube@master | |
with: | |
memory: 4000m | |
kubernetes-version: ${{ matrix.k8s-version }} | |
- name: Install Helm | |
uses: azure/setup-helm@v3 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
id: install | |
- name: Store creds | |
run: echo ${{ secrets.MONDOO_CLIENT }} | base64 -d > creds.json | |
- name: Extract Docker metadata | |
id: meta | |
uses: docker/metadata-action@v4 | |
with: | |
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
- name: Install Mondoo Operator Helm chart | |
run: helm install mondoo-operator charts/mondoo-operator -n mondoo-operator --create-namespace --wait | |
# Now that dependencies are cached the tests start almost immediately after minikube has started | |
# this makes tests fail occasionally. This sleep gives the runner some time to become more stable | |
# before the test execution starts. | |
- name: Wait a bit for the runner to become more stable | |
run: kubectl -n kube-system wait --for=condition=Ready pods --all --timeout=60s | |
- name: Run integration tests | |
env: | |
MONDOO_SERVICE_ACCOUNT_EDGE: ${{ secrets.MONDOO_SERVICE_ACCOUNT_EDGE }} | |
run: EXTERNAL_INSTALLATION=1 VERSION=${{ steps.meta.outputs.version }} make test/integration/ci | |
- name: Upload test logs artifact | |
uses: actions/upload-artifact@v3 | |
if: failure() | |
with: | |
name: helm-test-logs-${{ matrix.k8s-version }} | |
path: /home/runner/work/mondoo-operator/mondoo-operator/tests/integration/_output/ | |
- uses: dorny/test-reporter@v1 | |
if: failure() || success() | |
with: | |
name: Report Helm test results | |
path: '*.xml' # Path to test results | |
reporter: java-junit # Format of test results | |
release-helm: | |
name: Release helm chart | |
needs: | |
- run-helm-tests | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Configure Git | |
run: | | |
git config user.name "$GITHUB_ACTOR" | |
git config user.email "[email protected]" | |
- name: Install Helm | |
uses: azure/setup-helm@v3 | |
with: | |
token: ${{ secrets.GITHUB_TOKEN }} | |
id: install | |
- name: Run chart-releaser | |
# switch back to helm/chart-releaser-action when #60 is fixed | |
# https://github.com/helm/chart-releaser-action/issues/60 | |
uses: luisico/chart-releaser-action@on-tags | |
env: | |
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" |