Direct listener mode for the exporter #559
This file contains hidden or 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 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 |