Skip to content

test(e2e): infrastructure provider subprocess suite + CI job for prov… #76

test(e2e): infrastructure provider subprocess suite + CI job for prov…

test(e2e): infrastructure provider subprocess suite + CI job for prov… #76

name: Provider release (image + chart)
# Builds and publishes a single provider's container image and Helm chart from
# the monorepo, stamped with that provider's OWN version — not the hub version.
#
# Triggered by a per-provider release tag `providers/<name>/v<X.Y.Z>` (cut by
# `cmd/kedge-release`). The provider name and version are parsed from the tag;
# the image is tagged `vX.Y.Z` and `X.Y.Z`, and the chart's version/appVersion
# are set to that version. Because every provider chart leaves `image.tag` empty
# (→ defaults to `.Chart.AppVersion`), the deployed chart resolves to the
# matching provider-versioned image built here.
#
# This is the sole publisher of provider images/charts. The hub `v*` release
# (images.yaml / helm-images.yaml) builds providers in build-only PR validation
# mode and no longer publishes them, and the split-*.yaml mirrors publish source
# only (no version tag → no mirror image build), so there is no double-build.
on:
push:
tags:
- 'providers/*/v*'
permissions:
contents: read
packages: write
id-token: write
env:
REGISTRY: ghcr.io
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Parse provider + version from tag
id: tag
run: |
set -euo pipefail
# refs/tags/providers/<name>/vX.Y.Z
FULL="${GITHUB_REF#refs/tags/}" # providers/code/v0.0.9
REST="${FULL#providers/}" # code/v0.0.9
PROVIDER="${REST%%/*}" # code
VERSION="${FULL##*/}" # v0.0.9
[ -d "providers/${PROVIDER}" ] || { echo "unknown provider ${PROVIDER}"; exit 1; }
[ -f "providers/${PROVIDER}/Dockerfile" ] || { echo "no Dockerfile for ${PROVIDER}"; exit 1; }
# Image repo matches the provider chart's values.yaml image.repository.
# app-studio is published under a nested path; the rest are flat.
case "${PROVIDER}" in
app-studio) IMAGE="${{ github.repository_owner }}/kedge/app-studio-provider" ;;
*) IMAGE="${{ github.repository_owner }}/kedge-${PROVIDER}-provider" ;;
esac
echo "provider=${PROVIDER}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT" # v0.0.9 (chart appVersion + image tag)
echo "semver=${VERSION#v}" >> "$GITHUB_OUTPUT" # 0.0.9 (chart version, OCI convention)
echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push image
uses: docker/build-push-action@v6
with:
context: ./providers/${{ steps.tag.outputs.provider }}
file: ./providers/${{ steps.tag.outputs.provider }}/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ env.REGISTRY }}/${{ steps.tag.outputs.image }}:${{ steps.tag.outputs.version }}
${{ env.REGISTRY }}/${{ steps.tag.outputs.image }}:${{ steps.tag.outputs.semver }}
# The infrastructure provider ships a companion image: the dev-agent its
# kro backend injects into development-mode pods (providers/infrastructure/
# dev-agent, a scratch image carrying one static binary). It versions with
# the provider — publish it on the same tag so deployments can pin
# KEDGE_DEV_AGENT_IMAGE / development.agentImage to vX.Y.Z, and refresh
# :latest, which backs the in-binary default for stock deployments.
- name: Build and push dev-agent image
if: steps.tag.outputs.provider == 'infrastructure'
uses: docker/build-push-action@v6
with:
context: ./providers/infrastructure/dev-agent
file: ./providers/infrastructure/dev-agent/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/kedge-dev-agent:${{ steps.tag.outputs.version }}
${{ env.REGISTRY }}/${{ github.repository_owner }}/kedge-dev-agent:${{ steps.tag.outputs.semver }}
${{ env.REGISTRY }}/${{ github.repository_owner }}/kedge-dev-agent:latest
- name: Install Helm
uses: azure/setup-helm@v3
with:
version: 'v3.12.0'
- name: Package and push chart
env:
HELM_EXPERIMENTAL_OCI: 1
run: |
set -euo pipefail
echo "${{ github.token }}" | helm registry login "${REGISTRY}" --username ${{ github.actor }} --password-stdin
chart_dir="providers/${{ steps.tag.outputs.provider }}/deploy/chart/"
chart_name=$(grep -E '^name:' "${chart_dir}Chart.yaml" | head -1 | awk '{print $2}')
# Chart version follows OCI/semver convention (no 'v'); appVersion keeps
# the 'v' so the chart's image.tag default (.Chart.AppVersion) matches
# the 'vX.Y.Z' image tag pushed above.
CHART_VERSION="${{ steps.tag.outputs.semver }}"
APP_VERSION="${{ steps.tag.outputs.version }}"
# lint renders templates against default values (package only tars), so
# a broken template fails here rather than shipping.
helm lint "$chart_dir"
# Stamp version + appVersion at package time via flags rather than
# rewriting Chart.yaml, so the checked-out source is never mutated.
helm package "$chart_dir" --version "${CHART_VERSION}" --app-version "${APP_VERSION}"
helm push "${chart_name}-${CHART_VERSION}.tgz" "oci://${REGISTRY}/${{ github.repository_owner }}/charts"
echo "Pushed oci://${REGISTRY}/${{ github.repository_owner }}/charts/${chart_name}:${CHART_VERSION} (appVersion ${APP_VERSION})"