Skip to content

Direct listener mode for the exporter #559

Direct listener mode for the exporter

Direct listener mode for the exporter #559

Workflow file for this run

name: Build and push container images
on:
workflow_dispatch:
push:
tags:
- '*'
branches:
- main
- 'release-*'
pull_request:
types: [opened, synchronize, reopened, labeled]
merge_group:
env:
PUSH: ${{ github.repository_owner == 'jumpstarter-dev' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/release-') || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)) }}
REGISTRY: quay.io
QUAY_ORG: quay.io/jumpstarter-dev
jobs:
build-and-push-image:
if: github.event_name != 'pull_request' || contains(toJSON(github.event.pull_request.labels.*.name), 'build-pr-images')
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
strategy:
matrix:
include:
# Controller images
- image_name: jumpstarter-dev/jumpstarter-controller
label: jumpstarter-controller
dockerfile: controller/Dockerfile
context: controller
- image_name: jumpstarter-dev/jumpstarter-operator
label: jumpstarter-operator
dockerfile: controller/Dockerfile.operator
context: controller
- image_name: jumpstarter-dev/jumpstarter-operator-bundle
label: jumpstarter-operator-bundle
dockerfile: controller/deploy/operator/bundle.Dockerfile
context: controller/deploy/operator
generate_bundle: true
# Python images (use repo root context for .git access needed by hatch-vcs)
- image_name: jumpstarter-dev/jumpstarter
label: jumpstarter
dockerfile: python/Dockerfile
context: .
- image_name: jumpstarter-dev/jumpstarter-utils
label: jumpstarter-utils
dockerfile: python/Dockerfile.utils
context: python
- image_name: jumpstarter-dev/jumpstarter-dev
label: jumpstarter-dev
dockerfile: python/.devfile/Containerfile
context: python
- image_name: jumpstarter-dev/jumpstarter-devspace
label: jumpstarter-devspace
dockerfile: python/.devfile/Containerfile.client
context: .
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check if this image should be built
id: check
if: github.event_name == 'pull_request'
env:
LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }}
IMAGE_LABEL: ${{ matrix.label }}
run: |
# build-pr-images builds all images, build-pr-images/<label> builds a specific one
if echo "$LABELS" | jq -e 'index("build-pr-images")' > /dev/null 2>&1; then
echo "skip=false" >> $GITHUB_OUTPUT
elif echo "$LABELS" | jq -e --arg label "build-pr-images/$IMAGE_LABEL" 'index($label)' > /dev/null 2>&1; then
echo "skip=false" >> $GITHUB_OUTPUT
else
echo "skip=true" >> $GITHUB_OUTPUT
fi
- name: Get version
if: steps.check.outputs.skip != 'true'
run: |
VERSION=$(git describe --tags)
VERSION=${VERSION#v} # remove the leading v prefix for version
echo "VERSION=${VERSION}" >> $GITHUB_ENV
echo "VERSION=${VERSION}"
# Convert to PEP 440 compliant version for Python packages
# Format: 0.7.0-1051-g54cd2f08 -> 0.7.0.dev1051+g54cd2f08
if [[ "$VERSION" =~ ^([0-9]+\.[0-9]+\.[0-9]+)-([0-9]+)-g([a-f0-9]+)$ ]]; then
PEP440_VERSION="${BASH_REMATCH[1]}.dev${BASH_REMATCH[2]}+g${BASH_REMATCH[3]}"
else
# If it's already a clean version (e.g., 0.7.0), use as-is
PEP440_VERSION="$VERSION"
fi
echo "PEP440_VERSION=${PEP440_VERSION}" >> $GITHUB_ENV
echo "PEP440_VERSION=${PEP440_VERSION}"
- name: Set build args
if: steps.check.outputs.skip != 'true'
id: build-args
run: |
GIT_COMMIT=$(git rev-parse HEAD)
BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
echo "git_commit=${GIT_COMMIT}" >> $GITHUB_OUTPUT
echo "build_date=${BUILD_DATE}" >> $GITHUB_OUTPUT
echo "GIT_COMMIT=${GIT_COMMIT}"
echo "BUILD_DATE=${BUILD_DATE}"
- name: Generate operator bundle
if: ${{ matrix.generate_bundle && steps.check.outputs.skip != 'true' }}
run: make bundle VERSION=${{ env.VERSION }}
working-directory: controller/deploy/operator
- name: Set image tags
if: ${{ env.PUSH == 'true' && steps.check.outputs.skip != 'true' }}
id: set-tags
run: |
TAGS="${{ env.REGISTRY }}/${{ matrix.image_name }}:${{ env.VERSION }}"
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
TAGS="$TAGS,${{ env.REGISTRY }}/${{ matrix.image_name }}:latest"
fi
if [[ "${{ github.ref }}" == refs/heads/release-* ]]; then
RELEASE_BRANCH_NAME=$(basename "${{ github.ref }}")
TAGS="$TAGS,${{ env.REGISTRY }}/${{ matrix.image_name }}:${RELEASE_BRANCH_NAME}"
fi
echo "tags=$TAGS" >> $GITHUB_OUTPUT
- name: Set up QEMU
if: steps.check.outputs.skip != 'true'
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
if: steps.check.outputs.skip != 'true'
uses: docker/setup-buildx-action@v3
- name: Log in to the Container registry
uses: docker/login-action@v3
if: ${{ env.PUSH == 'true' && steps.check.outputs.skip != 'true' }}
with:
registry: ${{ env.REGISTRY }}
username: jumpstarter-dev+jumpstarter_ci
password: ${{ secrets.QUAY_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
if: steps.check.outputs.skip != 'true'
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ matrix.image_name }}
tags: |
type=ref,event=pr,prefix=pr-
labels: |
quay.expires-after=${{ github.event_name == 'pull_request' && '7d' || '' }}
- name: Build and push Docker image
if: steps.check.outputs.skip != 'true'
id: push
uses: docker/build-push-action@v6
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
push: ${{ env.PUSH }}
tags: ${{ github.event_name == 'pull_request' && steps.meta.outputs.tags || steps.set-tags.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
GIT_VERSION=${{ env.PEP440_VERSION }}
GIT_COMMIT=${{ steps.build-args.outputs.git_commit }}
BUILD_DATE=${{ steps.build-args.outputs.build_date }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
if: ${{ env.PUSH == 'true' && steps.check.outputs.skip != 'true' }}
with:
subject-name: ${{ env.REGISTRY }}/${{ matrix.image_name }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: ${{ env.PUSH }}
comment-pr-images:
needs: build-and-push-image
if: github.event_name == 'pull_request' && contains(toJSON(github.event.pull_request.labels.*.name), 'build-pr-images')
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Comment PR with image URIs
uses: actions/github-script@v8
with:
script: |
const prNumber = context.payload.pull_request.number;
const registry = 'quay.io';
const tag = `pr-${prNumber}`;
const labels = context.payload.pull_request.labels.map(l => l.name);
const buildAll = labels.includes('build-pr-images');
const allImages = [
'jumpstarter-dev/jumpstarter-controller',
'jumpstarter-dev/jumpstarter-operator',
'jumpstarter-dev/jumpstarter-operator-bundle',
'jumpstarter-dev/jumpstarter',
'jumpstarter-dev/jumpstarter-utils',
'jumpstarter-dev/jumpstarter-dev',
'jumpstarter-dev/jumpstarter-devspace',
];
const images = buildAll ? allImages : allImages.filter(img => {
const shortName = img.split('/')[1];
return labels.includes(`build-pr-images/${shortName}`);
});
if (images.length === 0) return;
const body = [
'## Container Images',
'',
'The following container images have been built for this PR:',
'',
'| Image | URI |',
'|-------|-----|',
...images.map(img => `| \`${img.split('/')[1]}\` | \`${registry}/${img}:${tag}\` |`),
'',
'_Images expire after 7 days._',
].join('\n');
// Update existing comment or create a new one
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const botComment = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('## Container Images')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
}
publish-helm-charts:
needs: build-and-push-image
if: ${{ github.repository_owner == 'jumpstarter-dev' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/release-')) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get version
run: |
VERSION=$(git describe --tags)
VERSION=${VERSION#v} # remove the leading v prefix for version
echo "VERSION=${VERSION}" >> $GITHUB_ENV
echo "VERSION=${VERSION}"
- name: Build helm charts
run: |
echo packaging ${VERSION}
# patch the sub-chart app-version, because helm package won't do it
sed -i "s/^appVersion:.*/appVersion: $VERSION/" controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yaml
helm package ./controller/deploy/helm/jumpstarter --version "${VERSION}" --app-version "${VERSION}"
- name: Login helm
env:
PASSWORD: ${{ secrets.QUAY_TOKEN }}
USER: jumpstarter-dev+jumpstarter_ci
run:
helm registry login quay.io -u ${USER} -p ${PASSWORD}
- name: Push helm charts
run: |
helm push jumpstarter-*.tgz oci://${{ env.QUAY_ORG }}/helm
if [[ "${{ github.ref }}" == "refs/heads/release-*" ]]; then
RELEASE_BRANCH_NAME=$(basename "${{ github.ref }}")
helm chart save jumpstarter-*.tgz ${{ env.QUAY_ORG }}/helm:${RELEASE_BRANCH_NAME}
helm chart push ${{ env.QUAY_ORG }}/helm:${RELEASE_BRANCH_NAME}
fi