Skip to content

Publish Container Images #1739

Publish Container Images

Publish Container Images #1739

Workflow file for this run

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:
REGISTRY: ghcr.io
GHCR_IMAGE: ghcr.io/${{ github.repository }}
GCP_IMAGE: us-docker.pkg.dev/mondoohq/release/mondoo-operator
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@v5
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@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Authenticate with Google Cloud
uses: "google-github-actions/auth@v2"
with:
credentials_json: "${{ secrets.GCP_ARTIFACT_REGISTRY_SA }}"
- name: "Set up Cloud SDK"
uses: "google-github-actions/setup-gcloud@v2"
- name: Docker Login (GCR)
run: |
gcloud auth configure-docker us-docker.pkg.dev
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.GHCR_IMAGE }}
${{ env.GCP_IMAGE }}
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@v5
with:
images: |
${{ env.GHCR_IMAGE }}
${{ env.GCP_IMAGE }}
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@v6
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.GHCR_IMAGE }}@${{ 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.GHCR_IMAGE }}@${{ 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@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Authenticate with Google Cloud
uses: "google-github-actions/auth@v2"
with:
credentials_json: "${{ secrets.GCP_ARTIFACT_REGISTRY_SA }}"
- name: "Set up Cloud SDK"
uses: "google-github-actions/setup-gcloud@v2"
- name: Docker Login (GCR)
run: |
gcloud auth configure-docker us-docker.pkg.dev
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.GHCR_IMAGE }}
${{ env.GCP_IMAGE }}
- 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@v5
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@v3
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@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@v3
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.GHCR_IMAGE }}:${{ 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@v5
with:
images: "${{ env.GHCR_IMAGE }}-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@v6
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.GHCR_IMAGE }}-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.28.9, v1.29.4, v1.30.0]
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@v5
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: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.GHCR_IMAGE }}
- name: Run integration tests
env:
MONDOO_API_TOKEN: ${{ secrets.MONDOO_TEST_ORG_TOKEN }}
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
- uses: actions/upload-artifact@v4 # upload test results
if: success() || failure() # run this step even if previous step failed
with: # upload a combined archive with unit and integration test results
name: test-results-olm-${{ matrix.k8s-version }}
path: integration-tests-olm-${{ matrix.k8s-version }}.xml
- name: Upload test logs artifact
uses: actions/upload-artifact@v4
if: failure()
with:
name: olm-test-logs-${{ matrix.k8s-version }}
path: /home/runner/work/mondoo-operator/mondoo-operator/tests/integration/_output/
# 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.26.12, v1.27.9, v1.28.5, v1.29.0]
# 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@v5
# 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@v4
# with:
# token: ${{ secrets.GITHUB_TOKEN }}
# id: install
# - name: Extract Docker metadata
# id: meta
# uses: docker/metadata-action@v5
# 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_API_TOKEN: ${{ secrets.MONDOO_TEST_ORG_TOKEN }}
# run: EXTERNAL_INSTALLATION=1 VERSION=${{ steps.meta.outputs.version }} make test/integration/ci
# - uses: actions/upload-artifact@v4 # upload test results
# if: success() || failure() # run this step even if previous step failed
# with: # upload a combined archive with unit and integration test results
# name: test-results-helm-${{ matrix.k8s-version }}
# path: integration-tests-helm-${{ matrix.k8s-version }}.xml
# - name: Upload test logs artifact
# uses: actions/upload-artifact@v4
# if: failure()
# with:
# name: helm-test-logs-${{ matrix.k8s-version }}
# path: /home/runner/work/mondoo-operator/mondoo-operator/tests/integration/_output/
report-tests:
name: Report test results
runs-on: ubuntu-latest
needs:
- run-olm-e2e
#- run-helm-tests
permissions:
actions: read # Required to read the artifact
contents: read # Required to read the source
checks: write # Required to write the results
pull-requests: write # Required to write comments
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
pattern: test-results-*
merge-multiple: true
- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
with:
commit: ${{ github.event.workflow_run.head_sha }}
event_file: ${{ github.event_path }}
event_name: ${{ github.event.workflow_run.event }}
files: "*.xml"
release-helm:
name: Release helm chart
needs:
- push-virtual-tag
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@v4
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 }}"