Pin github actions to commit hash #875
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: "Build" | |
on: | |
pull_request: | |
push: | |
branches: | |
- master | |
tags: | |
- "v*" | |
workflow_dispatch: {} | |
jobs: | |
# | |
# Building Stage | |
# | |
generate-version: | |
runs-on: ubuntu-latest | |
outputs: | |
version: ${{ steps.generate-version.outputs.version }} | |
is-public-build: ${{ steps.generate-version.outputs.is-public-build }} | |
is-release: ${{ steps.generate-version.outputs.is-release }} | |
steps: | |
- name: Detect Version | |
id: generate-version | |
run: | | |
$ref = '${{ github.ref }}' | |
if ($ref.StartsWith('refs/tags/v')) | |
{ | |
$version = ($ref -split '/v' | Select-Object -Last 1) | |
$isPublicBuild = $true | |
if ($ref.EndsWith('-pre')) | |
{ | |
$isRelease = $false | |
} | |
else | |
{ | |
$isRelease = $true | |
} | |
} | |
else | |
{ | |
$version = "0.0.1" | |
$isPublicBuild = $false | |
$isRelease = $false | |
} | |
Write-Host "Detected version: '$version'." | |
Write-Host "Is Release: '$isRelease'." | |
"version=$version" >> $env:GITHUB_OUTPUT | |
"is-public-build=$isPublicBuild" >> $env:GITHUB_OUTPUT | |
"is-release=$isRelease" >> $env:GITHUB_OUTPUT | |
shell: pwsh | |
build-image: | |
runs-on: ubuntu-latest | |
needs: generate-version | |
permissions: | |
packages: write | |
outputs: | |
digest: ${{ steps.build.outputs.digest }} | |
env: | |
IMAGE_NAME: ghcr.io/contrast-security-oss/agent-operator/operator | |
BUILD_VERSION: ${{ needs.generate-version.outputs.version }} | |
IS_PUBLIC_BUILD: ${{ needs.generate-version.outputs.is-public-build }} | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
submodules: true | |
- uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 | |
id: buildx | |
with: | |
install: true | |
version: latest | |
- uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 | |
with: | |
registry: ghcr.io | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Docker Meta | |
id: meta | |
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 | |
with: | |
images: ${{ env.IMAGE_NAME }} | |
tags: | | |
type=raw,value=trunk-artifact,enable=${{ github.ref == 'refs/heads/master' }} | |
type=raw,value=pr-artifact,enable=${{ github.event_name == 'pull_request' }} | |
type=raw,value=dispatch-artifact,enable=${{ github.event_name == 'workflow_dispatch' }} | |
type=raw,value=release-artifact,enable=${{ needs.generate-version.outputs.version != '0.0.1' }} | |
- uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 | |
id: build | |
with: | |
file: Dockerfile | |
context: . | |
push: ${{ github.event_name != 'pull_request' }} # don't push the image for PR builds | |
cache-from: ${{ github.actor != 'dependabot[bot]' && format('type=registry,ref={0}:cache', env.IMAGE_NAME) || ''}} | |
cache-to: ${{ github.actor != 'dependabot[bot]' && format('type=registry,ref={0}:cache,mode=max', env.IMAGE_NAME) || ''}} | |
build-args: | | |
BUILD_VERSION=${{ env.BUILD_VERSION }} | |
IS_PUBLIC_BUILD=${{ env.IS_PUBLIC_BUILD }} | |
tags: ${{ steps.meta.outputs.tags }} | |
labels: ${{ steps.meta.outputs.labels }} | |
build-manifests: | |
runs-on: ubuntu-latest | |
needs: generate-version | |
env: | |
BUILD_VERSION: ${{ needs.generate-version.outputs.version }} | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- uses: imranismail/setup-kustomize@2ba527d4d055ab63514ba50a99456fc35684947f # v2.1.0 | |
- name: Generate Manifests (Prod) | |
run: | | |
set -xe | |
cd ./manifests/install/prod | |
kustomize edit set image 'contrast/agent-operator:${{ env.BUILD_VERSION }}' | |
cat ../../license-header.yaml > ./install-prod.yaml | |
kustomize build ./ >> ./install-prod.yaml | |
shell: bash | |
- name: Generate Manifests (Prod-Quay) | |
run: | | |
set -xe | |
cd ./manifests/install/prod-quay | |
kustomize edit set image 'quay.io/contrast/agent-operator:${{ env.BUILD_VERSION }}' | |
cat ../../license-header.yaml > ./install-prod-quay.yaml | |
kustomize build ./ >> ./install-prod-quay.yaml | |
shell: bash | |
- name: Stage Manifests | |
run: | | |
set -xe | |
cp manifests/install/prod/install-prod.yaml ./install-prod.yaml | |
cp manifests/install/prod-quay/install-prod-quay.yaml ./install-prod-quay.yaml | |
shell: bash | |
- name: Publish (Artifacts) | |
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 | |
with: | |
name: manifests | |
path: | | |
install-prod.yaml | |
install-prod-quay.yaml | |
retention-days: 7 | |
build-helm-chart: | |
runs-on: ubuntu-latest | |
needs: generate-version | |
env: | |
BUILD_VERSION: ${{ needs.generate-version.outputs.version }} | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- uses: imranismail/setup-kustomize@2ba527d4d055ab63514ba50a99456fc35684947f # v2.1.0 | |
- uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 | |
with: | |
version: v3.10.1 | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Generate Chart | |
run: | | |
set -xe | |
pwsh ./manifests/helm/build.ps1 \ | |
-AppVersion ${{ env.BUILD_VERSION }} \ | |
-ChartVersion ${{ env.BUILD_VERSION }} | |
shell: bash | |
- name: Render Manifests | |
run: | | |
set -xe | |
helm template test \ | |
./manifests/helm/dist/contrast-agent-operator-${{ env.BUILD_VERSION }}.tgz \ | |
--values ./manifests/helm/values.testing.yaml \ | |
--include-crds \ | |
| tee ./manifests/helm/dist/output.yaml | |
shell: bash | |
- name: Publish (Chart) | |
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 | |
with: | |
name: helm-chart | |
path: | | |
manifests/helm/dist/*.tgz | |
retention-days: 7 | |
- name: Publish (Manifests) | |
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 | |
with: | |
name: helm-manifests | |
path: | | |
manifests/helm/dist/output.yaml | |
retention-days: 7 | |
test-image: | |
runs-on: ubuntu-latest | |
needs: | |
- build-image | |
strategy: | |
matrix: | |
k3s-version: | |
- '1.31' # EOL: 2025-10-28 | |
- '1.30' # EOL: 2025-06-28 | |
- '1.29' # EOL: 2025-02-28 | |
- '1.28' # EOL: 2024-10-28 | |
- '1.27' # EOL: 2024-06-28 | |
fail-fast: false | |
env: | |
IMAGE: ghcr.io/contrast-security-oss/agent-operator/operator@${{ needs.build-image.outputs.digest }} | |
if: ${{ github.event_name != 'pull_request' }} # should match push logic in build-image | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
submodules: true | |
- uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 | |
with: | |
registry: ghcr.io | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- uses: nolar/setup-k3d-k3s@293b8e5822a20bc0d5bcdd4826f1a665e72aba96 # v1.0.9 | |
name: Deploy K3d | |
with: | |
version: v${{ matrix.k3s-version }} | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Import Images | |
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0 | |
with: | |
timeout_minutes: 10 | |
max_attempts: 5 | |
command: | | |
set -xe | |
docker pull ${{ env.IMAGE }} | |
docker tag ${{ env.IMAGE }} local/agent-operator:latest | |
k3d image import local/agent-operator:latest --mode direct | |
docker pull busybox:stable | |
k3d image import busybox:stable --mode direct | |
docker pull k8s.gcr.io/pause:3.3 | |
k3d image import k8s.gcr.io/pause:3.3 --mode direct | |
shell: bash | |
- name: Deploy Manifests | |
run: | | |
set -xe | |
kubectl apply -k manifests/install/testing | |
kubectl --namespace testing-agent-operator wait --for=condition=Available --timeout=30s deployment contrast-agent-operator | |
kubectl apply -k manifests/examples/testing | |
shell: bash | |
- name: Setup .NET SDK | |
uses: actions/setup-dotnet@87b7050bc53ea08284295505d98d2aa94301e852 # v4.2.0 | |
with: | |
dotnet-version: 8.0.x | |
- name: Execute Functional Tests | |
run: | | |
set -xe | |
dotnet test ./tests/Contrast.K8s.AgentOperator.FunctionalTests/Contrast.K8s.AgentOperator.FunctionalTests.csproj | |
shell: bash | |
- name: Dump Operator Logs | |
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0 | |
if: ${{ always() }} | |
with: | |
timeout_minutes: 10 | |
max_attempts: 5 | |
command: | | |
set -xe | |
kubectl --namespace testing-agent-operator get events --sort-by=.metadata.creationTimestamp | |
kubectl --namespace testing-agent-operator get deployment contrast-agent-operator -o yaml | |
kubectl --namespace testing-agent-operator logs deployment/contrast-agent-operator | |
shell: bash | |
test-manifests: | |
runs-on: ubuntu-latest | |
needs: | |
- build-manifests | |
- build-helm-chart | |
strategy: | |
matrix: | |
artifact: | |
- manifests | |
- helm-manifests | |
k3s-version: | |
- '1.31' # EOL: 2025-10-28 | |
- '1.30' # EOL: 2025-06-28 | |
- '1.29' # EOL: 2025-02-28 | |
- '1.28' # EOL: 2024-10-28 | |
- '1.27' # EOL: 2024-06-28 | |
fail-fast: false | |
steps: | |
- name: Setup Pluto | |
uses: fairwindsops/pluto/github-action@d45f6d122de3d99fc4b7576592939ff62655db66 # v5.21.1 | |
- name: Setup Polaris | |
uses: fairwindsops/polaris/.github/actions/setup-polaris@80e6f7214ee611feb8a0ad2f8be6e58f822b868b # v9.6.1 | |
with: | |
version: 7.2.0 | |
- name: Setup Kubeconform | |
run: | | |
set -xe | |
wget https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz | |
tar xf kubeconform-linux-amd64.tar.gz | |
sudo install kubeconform /usr/local/bin/kubeconform | |
- name: Download Manifests | |
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 | |
id: download-artifacts | |
with: | |
name: ${{ matrix.artifact }} | |
path: ./artifacts | |
- name: Validate Manifests | |
run: | | |
set -xe | |
which kubeconform | |
which pluto | |
which polaris | |
for manifest in ./artifacts/*.yaml; | |
do | |
# https://github.com/yannh/kubeconform/issues/100#issuecomment-1096832969 | |
# Skipping the custom manifests for now. | |
kubeconform \ | |
--verbose \ | |
--summary \ | |
--kubernetes-version ${{ matrix.k3s-version }}.0 \ | |
-schema-location "default" \ | |
-schema-location "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{{ .NormalizedKubernetesVersion }}/{{ .ResourceKind }}{{ .KindSuffix }}.json" \ | |
-ignore-missing-schemas \ | |
$manifest | |
pluto detect \ | |
--output wide \ | |
--target-versions k8s=v${{ matrix.k3s-version }}.0 \ | |
$manifest | |
done | |
polaris audit \ | |
--audit-path ./artifacts/ \ | |
--set-exit-code-on-danger \ | |
--set-exit-code-below-score 90 | |
shell: bash | |
# | |
# Release Internal Stage | |
# | |
release-internal: | |
runs-on: ubuntu-latest | |
environment: internal | |
concurrency: | |
group: internal | |
needs: | |
- generate-version | |
- build-image | |
- test-image | |
- test-manifests | |
permissions: | |
packages: write | |
env: | |
BUILD_VERSION: ${{ needs.generate-version.outputs.version }} | |
IMAGE_NAME: ghcr.io/contrast-security-oss/agent-operator/operator | |
if: ${{ github.event_name != 'pull_request' && github.actor != 'dependabot[bot]' }} | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- name: Login (GitHub) | |
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 | |
with: | |
registry: ghcr.io | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Docker Meta | |
id: meta | |
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 | |
with: | |
images: ${{ env.IMAGE_NAME }} | |
tags: | | |
type=semver,pattern={{version}},value=${{ env.BUILD_VERSION }} | |
type=semver,pattern={{major}}.{{minor}},value=${{ env.BUILD_VERSION }},enable=${{ needs.generate-version.outputs.is-release == 'true' }} | |
type=semver,pattern={{major}},value=${{ env.BUILD_VERSION }},enable=${{ needs.generate-version.outputs.is-release == 'true' }} | |
type=raw,latest,enable=${{ needs.generate-version.outputs.is-release == 'true' }} | |
- name: Tag for Release | |
uses: akhilerm/tag-push-action@f35ff2cb99d407368b5c727adbcc14a2ed81d509 # v2.2.0 | |
with: | |
src: ghcr.io/contrast-security-oss/agent-operator/operator@${{ needs.build-image.outputs.digest }} | |
dst: | | |
${{ steps.meta.outputs.tags }} | |
# | |
# Release Public Stage | |
# | |
release-public: | |
runs-on: ubuntu-latest | |
environment: public | |
concurrency: | |
group: public | |
cancel-in-progress: true | |
needs: | |
- generate-version | |
- build-image | |
- release-internal | |
permissions: | |
contents: write | |
packages: write | |
env: | |
BUILD_VERSION: ${{ needs.generate-version.outputs.version }} | |
if: ${{ needs.generate-version.outputs.version != '0.0.1' }} | |
steps: | |
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
- name: Login (GitHub) | |
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 | |
with: | |
registry: ghcr.io | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Login (Dockerhub) | |
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_PAT }} | |
- name: Login (Quay) | |
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 | |
with: | |
registry: quay.io | |
username: ${{ secrets.QUAY_USERNAME }} | |
password: ${{ secrets.QUAY_PASSWORD }} | |
- name: Docker Meta | |
id: dockerhub-meta | |
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 | |
with: | |
images: | | |
docker.io/contrast/agent-operator | |
quay.io/contrast/agent-operator | |
ghcr.io/contrast-security-oss/agent-operator/operator | |
tags: | | |
type=semver,pattern={{version}},value=${{ env.BUILD_VERSION }} | |
type=semver,pattern={{major}}.{{minor}},value=${{ env.BUILD_VERSION }},enable=${{ needs.generate-version.outputs.is-release == 'true' }} | |
type=semver,pattern={{major}},value=${{ env.BUILD_VERSION }},enable=${{ needs.generate-version.outputs.is-release == 'true' }} | |
type=raw,latest,enable=${{ needs.generate-version.outputs.is-release == 'true' }} | |
- name: Tag for Release | |
uses: akhilerm/tag-push-action@f35ff2cb99d407368b5c727adbcc14a2ed81d509 # v2.2.0 | |
with: | |
src: ghcr.io/contrast-security-oss/agent-operator/operator@${{ needs.build-image.outputs.digest }} | |
dst: | | |
${{ steps.dockerhub-meta.outputs.tags }} | |
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 | |
id: download-artifacts | |
with: | |
name: manifests | |
path: ./artifacts | |
- name: Publish | |
uses: ncipollo/release-action@cdcc88a9acf3ca41c16c37bb7d21b9ad48560d87 # v1.15.0 | |
with: | |
body: | | |
Version v${{ env.BUILD_VERSION }} released! | |
``` | |
contrast/agent-operator:${{ env.BUILD_VERSION }} | |
contrast/agent-operator@${{ needs.build-image.outputs.digest }} | |
quay.io/contrast/agent-operator:${{ env.BUILD_VERSION }} | |
quay.io/contrast/agent-operator@${{ needs.build-image.outputs.digest }} | |
``` | |
artifacts: ${{ steps.download-artifacts.outputs.download-path }}/*.yaml | |
token: ${{ secrets.GITHUB_TOKEN }} | |
allowUpdates: true | |
prerelease: ${{ needs.generate-version.outputs.is-release == 'false' }} # pre-releases will have is-release false | |
- name: Publish Helm Chart | |
uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3.0.0 | |
if: ${{ needs.generate-version.outputs.is-release == 'true' }} | |
with: | |
token: ${{ secrets.GH_PR_WRITE_PAT }} | |
repository: Contrast-Security-OSS/helm-charts | |
event-type: oob-update | |
client-payload: | | |
{ | |
"type": "agent-operator", | |
"runId": "${{ github.run_id }}", | |
"artifactName": "helm-chart" | |
} | |
# - name: Create Sentry Release | |
# uses: getsentry/action-release@f6dfa3d84a1c740b94aa45255c5e032b744a095d # v1.9.0 | |
# with: | |
# environment: production | |
# ignore_empty: true | |
# # BUILD_VERSION is the semantic version, but the operator will send the .NET version i.e. X.X.X.X. | |
# version: agent-operator@${{ env.BUILD_VERSION }}.0 | |
# env: | |
# SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
# SENTRY_ORG: sentry | |
# SENTRY_PROJECT: agent-operator | |
# SENTRY_URL: https://sentry.prod.dotnet.contsec.com | |
- uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0 | |
if: ${{ needs.generate-version.outputs.is-release == 'true' }} | |
with: | |
status: ${{ job.status }} | |
message: |- | |
Version <https://github.com/Contrast-Security-OSS/agent-operator/releases/tag/v${{ env.BUILD_VERSION }}|v${{ env.BUILD_VERSION }}> of the agent-operator was released! | |
fallback: |- | |
[GitHub] Version v${{ env.BUILD_VERSION }} of the agent-operator was released! | |
env: | |
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} |