Skip to content

pipeline

pipeline #1167

Workflow file for this run

name: pipeline
on:
schedule:
- cron: 0 0 * * *
push:
branches:
- develop
- feat/*
- hotfix/*
- main
pull_request:
branches:
- develop
- feat/*
- hotfix/*
- main
env:
CONTAINER_NAME: ${{ github.repository }}
CONTAINER_REGISTRY_GHCR: ghcr.io
CONTAINER_REGISTRY_DOCKER_HUB: docker.io
# https://github.com/sigstore/cosign/releases
COSIGN_VERSION: 2.2.0
# https://npmjs.com/package/@microsoft/sarif-multitool?activeTab=versions
SARIF_MULTITOOL_VERSION: 4.3.0
# https://npmjs.com/package/snyk?activeTab=versions
SNYK_VERSION: 1.1200.0
# https://github.com/microsoft/azure-pipelines-agent/releases
AZP_AGENT_VERSION: 3.225.0
# https://github.com/PowerShell/PowerShell/releases
POWERSHELL_VERSION: 7.2.13
# https://github.com/krallin/tini/releases
TINI_VERSION: 0.19.0
# https://github.com/mikefarah/yq/releases
YQ_VERSION: 4.35.1
# https://go.dev/dl
GO_VERSION: 1.21.0
# https://github.com/rootless-containers/rootlesskit/releases
ROOTLESSKIT_VERSION: 1.1.1
# https://github.com/moby/buildkit/releases
BUILDKIT_VERSION: 0.12.1
# https://github.com/Azure/azure-cli/releases
AZURE_CLI_VERSION: 2.51.0
# https://github.com/stedolan/jq/releases
JQ_VERSION: 1.6
# https://github.com/aws/aws-cli/tags
AWS_CLI_VERSION: 2.13.9
# https://cloud.google.com/sdk/docs/install
GCLOUD_CLI_VERSION: 442.0.0
# https://github.com/git-for-windows/git/releases
GIT_WIN_VERSION: 2.41.0
# https://github.com/facebook/zstd/releases
ZSTD_WIN_VERSION: 1.5.5
# https://www.python.org/downloads/windows
PYTHON_WIN_VERSION: 3.11.4
# https://nodejs.org/en/download/releases
NODE_VERSION: 18.17.1
# https://github.com/helm/helm/releases
HELM_VERSION: 3.12.3
# https://github.com/oras-project/oras/releases
ORAS_VERSION: 1.0.1
# https://github.com/docker/buildx/releases
BUILDX_VERSION: 0.11.2
# https://github.com/hadolint/hadolint/releases
HADOLINT_VERSION: 2.12.0
# https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022
VS_BUILDTOOLS_WIN_VERSION: 17
jobs:
sast-creds:
name: SAST - Credentials
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/[email protected]
with:
# We need all Git history for testing credentials
fetch-depth: 0
# Ensure all submodules up-to-date
submodules: recursive
- name: SAST - Credentials
uses: trufflesecurity/[email protected]
with:
base: ${{ github.event.repository.default_branch }}
head: HEAD
path: .
build-helm:
name: Build Helm chart
needs:
- sast-creds
- sast-semgrep
- test
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/[email protected]
with:
# We need all Git history for "version.sh"
fetch-depth: 0
# Ensure "version.sh" submodule are up-to-date
submodules: recursive
- name: Version
id: version
run: |
echo "version=$(bash cicd/version/version.sh -g . -c)" >> $GITHUB_OUTPUT
echo "version_full=$(bash cicd/version/version.sh -g . -c -m)" >> $GITHUB_OUTPUT
- name: Setup Helm
uses: azure/[email protected]
with:
version: v${{ env.HELM_VERSION }}
# Required for running "npx" CLI
- name: Setup Node
uses: actions/[email protected]
with:
node-version: ${{ env.NODE_VERSION }}
- name: Setup Cosign
uses: sigstore/[email protected]
with:
cosign-release: v${{ env.COSIGN_VERSION }}
- name: Prepare GPG key
run: |
echo "${{ secrets.GPG_KEYRING }}" | gpg --dearmor > keyring.gpg
- name: Package Helm chart
run: |
cp README.md src/helm/azure-pipelines-agent/
helm package \
--app-version ${{ env.AZP_AGENT_VERSION }} \
--destination .cr-release-packages \
--key 'Clémence Lesné' \
--keyring keyring.gpg \
--sign \
--version ${{ steps.version.outputs.version }} \
src/helm/azure-pipelines-agent
- name: Sign Helm chart
env:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
run: |
cosign sign-blob \
--bundle .cr-release-packages/azure-pipelines-agent-${{ steps.version.outputs.version }}.tgz.bundle \
--key="env://COSIGN_PRIVATE_KEY" \
--yes \
.cr-release-packages/azure-pipelines-agent-${{ steps.version.outputs.version }}.tgz
- name: Cache Helm chart
uses: actions/[email protected]
with:
name: helm-chart
path: .cr-release-packages
- name: Render Helm chart locally
run: |
helm template \
--output-dir .helm-template \
--values test/helm/azure-pipelines-agent/values.yaml \
.cr-release-packages/azure-pipelines-agent-${{ steps.version.outputs.version }}.tgz
- name: Run SAST Snyk for Helm
# Snyk can be used to break the build when it detects security issues. In this case we want to upload the issues to GitHub Security
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
run: |
npx --yes snyk@${{ env.SNYK_VERSION }} iac test \
--sarif-file-output=snyk.sarif \
--severity-threshold=medium \
.helm-template
# Fix issue "Error: Code Scanning could not process the submitted SARIF file: rejecting SARIF, as there are more runs than allowed (XX > 20)"
# See: https://github.com/github/codeql-action/issues/220
- name: Merge SARIF files
run: |
npx --yes @microsoft/sarif-multitool@${{ env.SARIF_MULTITOOL_VERSION }} merge \
--automation-id ${{ github.run_id }} \
--merge-empty-logs \
--merge-runs \
--output-file merged.sarif \
snyk.sarif
- name: Upload results to GitHub Security
uses: github/codeql-action/[email protected]
with:
sarif_file: merged.sarif
deploy-helm:
name: Deploy Helm chart
needs:
- build-publish-linux
- build-publish-win
- build-helm
# Only deploy on non-scheduled main branch, as there is only one Helm repo and we cannot override an existing version
if: (github.event_name != 'schedule') && (github.ref == 'refs/heads/main')
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/[email protected]
with:
# Chart Releaser needs to have local access to "gh-pages" plus current branch
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
- name: Download Helm chart
uses: actions/[email protected]
with:
name: helm-chart
path: .cr-release-packages
- name: Archive Helm chart
uses: helm/[email protected]
with:
charts_dir: src/helm
skip_packaging: true
env:
CR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
test:
name: Test
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/[email protected]
# Required for running "npx" CLI
- name: Setup Node
uses: actions/[email protected]
with:
node-version: ${{ env.NODE_VERSION }}
- name: Setup Hadolint
run: |
sudo curl -LsSf --retry 4 https://github.com/hadolint/hadolint/releases/download/v${{ env.HADOLINT_VERSION }}/hadolint-Linux-x86_64 -o /usr/bin/hadolint
sudo chmod +x /usr/bin/hadolint
hadolint --version
- name: Run tests
run: |
make test
build-publish-linux:
name: Build & deploy image (Linux ${{ matrix.os }})
needs:
- sast-creds
- sast-semgrep
- test
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
include:
- os: bookworm
arch: linux/amd64,linux/arm64
- os: bullseye
arch: linux/amd64,linux/arm64
- os: focal
arch: linux/amd64,linux/arm64
- os: jammy
arch: linux/amd64,linux/arm64
- os: ubi8
arch: linux/amd64,linux/arm64
steps:
- name: Checkout
uses: actions/[email protected]
with:
# We need all Git history for "version.sh"
fetch-depth: 0
# Ensure "version.sh" submodule are up-to-date
submodules: recursive
- name: Configure Git
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
- name: Version
id: version
run: |
echo "version=$(bash cicd/version/version.sh -g . -c)" >> $GITHUB_OUTPUT
echo "version_full=$(bash cicd/version/version.sh -g . -c -m)" >> $GITHUB_OUTPUT
- name: Setup QEMU
id: setup-qemu
uses: docker/[email protected]
with:
platforms: ${{ matrix.arch }}
- name: Setup Docker Buildx
uses: docker/[email protected]
with:
version: v${{ env.BUILDX_VERSION }}
driver-opts: |
image=moby/buildkit:v${{ env.BUILDKIT_VERSION }}
# Required for running "npx" CLI
- name: Setup Node
uses: actions/[email protected]
with:
node-version: ${{ env.NODE_VERSION }}
- name: Setup Cosign
uses: sigstore/[email protected]
with:
cosign-release: v${{ env.COSIGN_VERSION }}
- name: Login to registry - GitHub
uses: docker/[email protected]
with:
registry: ${{ env.CONTAINER_REGISTRY_GHCR }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to registry - Docker Hub
uses: docker/[email protected]
with:
registry: ${{ env.CONTAINER_REGISTRY_DOCKER_HUB }}
username: clemlesne
password: ${{ secrets.DOCKER_HUB_PAT }}
- name: Check if pre-release
id: prerelease
run: |
if [ "${{ github.ref_name }}" == "${{ github.event.repository.default_branch }}" ]; then
echo "prerelease=false" >> $GITHUB_OUTPUT
else
echo "prerelease=true" >> $GITHUB_OUTPUT
fi
- name: Container meta
id: meta
uses: docker/[email protected]
with:
images: |
${{ env.CONTAINER_REGISTRY_GHCR }}/${{ env.CONTAINER_NAME }}
${{ env.CONTAINER_REGISTRY_DOCKER_HUB }}/${{ env.CONTAINER_NAME }}
flavor: |
prefix=${{ matrix.os }}-
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=branch
type=ref,event=pr
type=schedule
type=schedule,pattern={{date 'YYYYMMDD'}}
type=semver,pattern={{version}},value=${{ steps.version.outputs.version_full }}
type=sha
labels: |
io.artifacthub.package.category=integration-delivery
io.artifacthub.package.keywords=agent,azure,azure-devops,azure-pipelines,container,devops,docker,helm,kubernetes,pipelines,self-hosted,self-hosted-agent,auto-scale,keda
io.artifacthub.package.license=Apache-2.0
io.artifacthub.package.logo-url=https://raw.githubusercontent.com/${{ env.CONTAINER_NAME }}/${{ github.sha }}/logo-1024.png
io.artifacthub.package.maintainers=[{"name":"${{ github.actor }}","email":"${{ github.actor }}@users.noreply.github.com"}]
io.artifacthub.package.prerelease=${{ steps.prerelease.outputs.prerelease }}
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/${{ env.CONTAINER_NAME }}/${{ github.sha }}/README.md
org.opencontainers.image.documentation=https://github.com/${{ env.CONTAINER_NAME }}
org.opencontainers.image.vendor=${{ github.actor }}
- name: Store tag
id: tag
run: |
branch=$(echo "${{ github.ref_name }}" | sed 's/\//-/g')
tag=$(echo "${{ steps.meta.outputs.tags }}" | grep -m1 $branch)
echo "tag=$tag" >> $GITHUB_OUTPUT
- name: Build & push container
uses: docker/[email protected]
with:
build-args: |
AWS_CLI_VERSION=${{ env.AWS_CLI_VERSION }}
GCLOUD_CLI_VERSION=${{ env.GCLOUD_CLI_VERSION }}
AZP_AGENT_VERSION=${{ env.AZP_AGENT_VERSION }}
AZURE_CLI_VERSION=${{ env.AZURE_CLI_VERSION }}
BUILDKIT_VERSION=${{ env.BUILDKIT_VERSION }}
GO_VERSION=${{ env.GO_VERSION }}
JQ_VERSION=${{ env.JQ_VERSION }}
POWERSHELL_VERSION=${{ env.POWERSHELL_VERSION }}
ROOTLESSKIT_VERSION=${{ env.ROOTLESSKIT_VERSION }}
TINI_VERSION=${{ env.TINI_VERSION }}
YQ_VERSION=${{ env.YQ_VERSION }}
cache-from: type=gha
cache-to: type=gha
context: src/docker
file: src/docker/Dockerfile-${{ matrix.os }}
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ matrix.arch }}
provenance: true
outputs: type=registry,oci-mediatypes=true,compression=estargz,compression-level=9,force-compression=true
sbom: true
tags: ${{ steps.meta.outputs.tags }}
- name: Sign containers
env:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
run: |
while IFS= read -r tag; do
echo "Signing $tag..."
cosign sign \
--key="env://COSIGN_PRIVATE_KEY" \
--recursive \
--yes \
$tag
done <<< "${{ steps.meta.outputs.tags }}"
- name: Run SAST Snyk against containers
# Snyk can be used to break the build when it detects security issues. In this case we want to upload the issues to GitHub Security
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
run: |
for arch in $(echo ${{ matrix.arch }} | tr "," "\n"); do
echo "Running Snyk for $arch..."
npx --yes snyk@${{ env.SNYK_VERSION }} container test \
--architecture=$arch \
--fail-on=upgradable \
--file=src/docker/Dockerfile-${{ matrix.os }} \
--sarif-file-output=snyk-$(echo $arch | sed -e 's#/#-#g').sarif \
--severity-threshold=medium \
${{ steps.tag.outputs.tag }}
done
- name: Merge SARIF files
run: |
npx --yes @microsoft/sarif-multitool@${{ env.SARIF_MULTITOOL_VERSION }} merge \
--automation-id ${{ github.run_id }} \
--merge-empty-logs \
--merge-runs \
--output-file merged.sarif \
*.sarif
- name: Upload results to GitHub Security
uses: github/codeql-action/[email protected]
with:
sarif_file: merged.sarif
build-publish-win:
name: Build & deploy image (Windows ${{ matrix.os }})
needs:
- sast-creds
- sast-semgrep
- test
runs-on: ${{ matrix.runs-on }}
strategy:
fail-fast: false
matrix:
include:
- os: win-ltsc2022
runs-on: windows-2022
- os: win-ltsc2019
runs-on: windows-2019
steps:
- name: Checkout
uses: actions/[email protected]
with:
# We need all Git history for "version.sh"
fetch-depth: 0
# Ensure "version.sh" submodule are up-to-date
submodules: recursive
- name: Configure Git
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
- name: Version
id: version
run: |
echo "version=$(powershell cicd/version/version.ps1 -g . -c)" >> $Env:GITHUB_OUTPUT
echo "version_full=$(powershell cicd/version/version.ps1 -g . -c -m)" >> $Env:GITHUB_OUTPUT
# Required for running "npx" CLI
- name: Setup Node
uses: actions/[email protected]
with:
node-version: ${{ env.NODE_VERSION }}
- name: Setup Cosign
uses: sigstore/[email protected]
with:
cosign-release: v${{ env.COSIGN_VERSION }}
- name: Login to registry - GitHub
uses: docker/[email protected]
with:
registry: ${{ env.CONTAINER_REGISTRY_GHCR }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to registry - Docker Hub
uses: docker/[email protected]
with:
registry: ${{ env.CONTAINER_REGISTRY_DOCKER_HUB }}
username: clemlesne
password: ${{ secrets.DOCKER_HUB_PAT }}
- name: Check if pre-release
id: prerelease
run: |
if ('${{ github.ref_name }}' -eq '${{ github.event.repository.default_branch }}') {
echo "prerelease=false" >> $env:GITHUB_OUTPUT
} else {
echo "prerelease=true" >> $env:GITHUB_OUTPUT
}
- name: Container meta
id: meta
uses: docker/[email protected]
with:
images: |
${{ env.CONTAINER_REGISTRY_GHCR }}/${{ env.CONTAINER_NAME }}
${{ env.CONTAINER_REGISTRY_DOCKER_HUB }}/${{ env.CONTAINER_NAME }}
flavor: |
prefix=${{ matrix.os }}-
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=branch
type=ref,event=pr
type=schedule
type=schedule,pattern={{date 'YYYYMMDD'}}
type=semver,pattern={{version}},value=${{ steps.version.outputs.version_full }}
type=sha
labels: |
io.artifacthub.package.category=integration-delivery
io.artifacthub.package.keywords=agent,azure,azure-devops,azure-pipelines,container,devops,docker,helm,kubernetes,pipelines,self-hosted,self-hosted-agent,auto-scale,keda
io.artifacthub.package.license=Apache-2.0
io.artifacthub.package.logo-url=https://raw.githubusercontent.com/${{ env.CONTAINER_NAME }}/${{ github.sha }}/logo-1024.png
io.artifacthub.package.maintainers=[{"name":"${{ github.actor }}","email":"${{ github.actor }}@users.noreply.github.com"}]
io.artifacthub.package.prerelease=${{ steps.prerelease.outputs.prerelease }}
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/${{ env.CONTAINER_NAME }}/${{ github.sha }}/README.md
org.opencontainers.image.documentation=https://github.com/${{ env.CONTAINER_NAME }}
org.opencontainers.image.vendor=${{ github.actor }}
- name: Store tag
id: tag
run: |
$branch = "${{ github.ref_name }}".Replace("/", "-")
$tag = ('${{ steps.meta.outputs.tags }}').Split([Environment]::NewLine) | Where-Object { $_ -like "*$branch*" } | Select-Object -First 1
echo "tag=$tag" >> $Env:GITHUB_OUTPUT
- name: Build & push container
run: |
$params = @(
# Required build arguments
"--build-arg", "AWS_CLI_VERSION=${{ env.AWS_CLI_VERSION }}",
"--build-arg", "AZP_AGENT_VERSION=${{ env.AZP_AGENT_VERSION }}",
"--build-arg", "AZURE_CLI_VERSION=${{ env.AZURE_CLI_VERSION }}",
"--build-arg", "GCLOUD_CLI_VERSION=${{ env.GCLOUD_CLI_VERSION }}",
"--build-arg", "GIT_VERSION=${{ env.GIT_WIN_VERSION }}",
"--build-arg", "JQ_VERSION=${{ env.JQ_VERSION }}",
"--build-arg", "POWERSHELL_VERSION=${{ env.POWERSHELL_VERSION }}",
"--build-arg", "PYTHON_VERSION=${{ env.PYTHON_WIN_VERSION }}",
"--build-arg", "VS_BUILDTOOLS_VERSION=${{ env.VS_BUILDTOOLS_WIN_VERSION }}",
"--build-arg", "YQ_VERSION=${{ env.YQ_VERSION }}",
"--build-arg", "ZSTD_VERSION=${{ env.ZSTD_WIN_VERSION }}",
"--file", "src/docker/Dockerfile-${{ matrix.os }}"
)
$tags = ('${{ steps.meta.outputs.tags }}').Split([Environment]::NewLine)
foreach ($tag in $tags) {
$params += "--tag", $tag
}
# Default cache locations
$params += "--cache-from", "${{ env.CONTAINER_REGISTRY_GHCR }}/${{ env.CONTAINER_NAME }}:${{ matrix.os }}-develop"
$params += "--cache-from", "${{ env.CONTAINER_REGISTRY_GHCR }}/${{ env.CONTAINER_NAME }}:${{ matrix.os }}-${{ github.event.repository.default_branch }}"
# Branch-specific cache locations
foreach ($tag in $tags) {
$params += "--cache-from", $tag
}
$labels = ('${{ steps.meta.outputs.labels }}').Split([Environment]::NewLine)
foreach ($label in $labels) {
$params += "--label", $label
}
Write-Host "Build arguments:"
$params | ForEach-Object -Begin { $i = 0 } -Process {
if ($i % 2 -eq 0) {
Write-Host -NoNewline "`n $_"
} else {
Write-Host -NoNewline " $_"
}
$i++
}
Write-Host
Write-Host "Pulling cache images:"
foreach ($tag in $tags) {
Write-Host " $tag"
docker pull --quiet $tag || true
}
Write-Host "Building..."
docker build @params src\docker
Write-Host "Pushing..."
foreach ($tag in $tags) {
docker push --quiet $tag
}
- name: Sign containers
env:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
run: |
$tags = ('${{ steps.meta.outputs.tags }}').Split([Environment]::NewLine)
foreach ($tag in $tags) {
Write-Host "Signing $tag..."
cosign sign `
--key="env://COSIGN_PRIVATE_KEY" `
--recursive `
--yes `
$tag
}
- name: Run SAST Snyk against containers
# Snyk can be used to break the build when it detects security issues. In this case we want to upload the issues to GitHub Security
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
run: |
npx --yes snyk@${{ env.SNYK_VERSION }} container test `
--fail-on=upgradable `
--file=src/docker/Dockerfile-${{ matrix.os }} `
--sarif-file-output=snyk.sarif `
--severity-threshold=medium `
${{ steps.tag.outputs.tag }}
- name: Upload results to GitHub Security
uses: github/codeql-action/[email protected]
with:
sarif_file: snyk.sarif
sast-semgrep:
name: SAST - Semgrep
runs-on: ubuntu-22.04
container:
image: returntocorp/semgrep
steps:
- name: Checkout
uses: actions/[email protected]
- name: Run tests
# Semgrep can be used to break the build when it detects security issues. In this case we want to upload the issues to GitHub Security
continue-on-error: true
env:
SEMGREP_RULES: p/cwe-top-25 p/owasp-top-ten p/kubernetes p/dockerfile
run: semgrep ci --sarif --output=semgrep.sarif
- name: Upload results to GitHub Security
uses: github/codeql-action/[email protected]
with:
sarif_file: semgrep.sarif
deploy-artifacthub-metadata:
name: Deploy ArtifactHub metadata
# Only deploy on main branch, as we don't want to break verification with a bad metadata file during development
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/[email protected]
- name: Setup ORAS
uses: oras-project/[email protected]
with:
version: ${{ env.ORAS_VERSION }}
- name: Login to registry - GitHub
uses: docker/[email protected]
with:
registry: ${{ env.CONTAINER_REGISTRY_GHCR }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to registry - Docker Hub
uses: docker/[email protected]
with:
registry: ${{ env.CONTAINER_REGISTRY_DOCKER_HUB }}
username: clemlesne
password: ${{ secrets.DOCKER_HUB_PAT }}
- name: Push to registry
run: |
oras push \
${{ env.CONTAINER_REGISTRY_GHCR }}/${{ env.CONTAINER_NAME }}:artifacthub.io \
artifacthub-repo.yml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yaml \
--config /dev/null:application/vnd.cncf.artifacthub.config.v1+yaml
oras push \
${{ env.CONTAINER_REGISTRY_DOCKER_HUB }}/${{ env.CONTAINER_NAME }}:artifacthub.io \
artifacthub-repo.yml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yaml \
--config /dev/null:application/vnd.cncf.artifacthub.config.v1+yaml