From c6819b8d311be071e1f598aab5b935999e2b6fbb Mon Sep 17 00:00:00 2001 From: Paul Meyer <49727155+katexochen@users.noreply.github.com> Date: Wed, 16 Aug 2023 10:42:40 +0200 Subject: [PATCH] ci: automatically build GCP CCM container Signed-off-by: Paul Meyer <49727155+katexochen@users.noreply.github.com> --- .../actions/gcpccm_vers_to_build/action.yml | 24 +++++ .../actions/gcpccm_vers_to_build/findvers.sh | 84 ++++++++++++++++++ .github/workflows/build-ccm-gcp.yml | 87 ++++++++++++++----- 3 files changed, 174 insertions(+), 21 deletions(-) create mode 100644 .github/actions/gcpccm_vers_to_build/action.yml create mode 100755 .github/actions/gcpccm_vers_to_build/findvers.sh diff --git a/.github/actions/gcpccm_vers_to_build/action.yml b/.github/actions/gcpccm_vers_to_build/action.yml new file mode 100644 index 000000000..de45d25fc --- /dev/null +++ b/.github/actions/gcpccm_vers_to_build/action.yml @@ -0,0 +1,24 @@ +name: Find GCP CCM versions that need to be build +description: Find GCP CCM versions that need to be build + +inputs: + path: + description: "Path to the GCP CCM repository" + required: true + +outputs: + versions: + description: "Versions that need to be build" + value: ${{ steps.find-versions.outputs.versions }} + +runs: + using: "composite" + steps: + - name: Find versions that need to be build + id: find-versions + shell: bash + run: | + script=$(realpath .github/actions/gcpccm_vers_to_build/findvers.sh) + pushd "${{ inputs.path }}" + versions=$(${script}) + echo "versions=${versions}" | tee -a "$GITHUB_OUTPUT" diff --git a/.github/actions/gcpccm_vers_to_build/findvers.sh b/.github/actions/gcpccm_vers_to_build/findvers.sh new file mode 100755 index 000000000..659e89b85 --- /dev/null +++ b/.github/actions/gcpccm_vers_to_build/findvers.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +set -euo pipefail + +function info() { + echo "$@" 1>&2 +} + +function error() { + echo "::err::$*" + exit 1 +} + +allCCMVersions=$(git tag | grep ccm || test $? = 1) +if [[ -z ${allCCMVersions} ]]; then + error "No CCM tags found in git" +fi + +allMajorVersions=() + +for ver in ${allCCMVersions}; do + major=${ver#ccm/v} # remove "ccm/v" prefix + major=${major%%.*} # remove everything after the first dot + + if [[ ${major} -eq 0 ]]; then + continue # skip major version 0 + fi + + # Check if this major version is already in the list. + for existingMajor in "${allMajorVersions[@]}"; do + if [[ ${existingMajor} -eq ${major} ]]; then + continue 2 + fi + done + + info "Found major version ${major}" + allMajorVersions+=("${major}") +done + +if [[ ${#allMajorVersions[@]} -eq 0 ]]; then + error "No major versions found in CCM tags" +fi + +existingContainerVersions=$(crane ls "ghcr.io/edgelesssys/cloud-provider-gcp") +if [[ -z ${existingContainerVersions} ]]; then + info "No existing container versions found" +fi + +versionsToBuild=() + +for major in "${allMajorVersions[@]}"; do + # Get the latest released version with this major version. + latest=$(echo "${allCCMVersions[@]}" | grep "${major}" | sort -V | tail -n 1) + latest=${latest#ccm/} # remove "ccm/" prefix, keep v + if [[ -z ${latest} ]]; then + error "Could not determine latest version with major ${major}" + fi + info "Latest ${major} version is ${latest}" + + # Find the latest version with this major version. + majorVerRegexp="v${major}.[0-9]+.[0-9]+" + allExistingWithMajor=$(grep -E "${majorVerRegexp}" <<< "${existingContainerVersions}" || test $? = 1) + latestExistingWithMinor=$(echo "${allExistingWithMajor}" | sort -V | tail -n 1) + + # If there is no existing version with this major version, build the latest released version. + if [[ -z ${latestExistingWithMinor} ]]; then + info "No existing version with major ${major}, adding ${latest} to versionsToBuild" + versionsToBuild+=("${latest}") + continue + fi + info "Latest existing version with major ${major} is ${latestExistingWithMinor}" + + newerVer=$(echo -e "${latest}\n${latestExistingWithMinor}" | sort -V | tail -n 1) + if [[ ${newerVer} == "${latestExistingWithMinor}" ]]; then + info "Existing version ${latestExistingWithMinor} is up to date, skipping" + continue + fi + + info "Newer version ${latest} is available, existing version is ${latestExistingWithMinor}." + info "Adding ${latest} to versionsToBuild" + versionsToBuild+=("${latest}") +done + +printf '%s\n' "${versionsToBuild[@]}" | jq -R | jq -sc diff --git a/.github/workflows/build-ccm-gcp.yml b/.github/workflows/build-ccm-gcp.yml index d319adff3..79d1cac0d 100644 --- a/.github/workflows/build-ccm-gcp.yml +++ b/.github/workflows/build-ccm-gcp.yml @@ -1,29 +1,75 @@ name: Build and Upload GCP CCM container image -env: - REGISTRY: ghcr.io -on: [workflow_dispatch] + +on: + push: + branches: + - 'main' + paths: + - '.github/workflows/build-ccm-gcp.yml' + - '.github/actions/gcpccm_vers_to_build/**' + schedule: + - cron: "0 4 * * 3" # Every Wednesday at 4am UTC + workflow_dispatch: jobs: + find-ccm-versions: + runs-on: ubuntu-22.04 + outputs: + versions: ${{ steps.find-versions.outputs.versions }} + latest: ${{ steps.find-latest.outputs.latest }} + steps: + - name: Checkout Constellation + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + - name: Checkout kubernetes/cloud-provider-gcp + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + repository: "kubernetes/cloud-provider-gcp" + path: "cloud-provider-gcp" + fetch-depth: 0 + + - name: Setup Go environment + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version: "1.20.7" + cache: false + + - name: Install Crane + run: | + go install github.com/google/go-containerregistry/cmd/crane@latest + + - name: Find versions + id: find-versions + uses: ./.github/actions/gcpccm_vers_to_build + with: + path: "cloud-provider-gcp" + + - name: Find latest + id: find-latest + run: | + rawList=$(jq -r '.[]' <<< '${{ steps.find-versions.outputs.versions }}') + lastest=$(echo "${rawList}" | sort -V | tail -n 1) + echo "latest=${lastest}" | tee -a "$GITHUB_OUTPUT" + build-ccm-gcp: runs-on: ubuntu-22.04 permissions: contents: read packages: write + needs: find-ccm-versions strategy: + fail-fast: false matrix: - version: [v26.0.1] - # TODO(katexochen): Once issue is closed upgrade older versions, rebuild, and update versions.go - # https://github.com/kubernetes/cloud-provider-gcp/issues/451 - # Alternativly, they start to publish releases themselves and we can remove this workflow (see https://github.com/kubernetes/cloud-provider-gcp/issues/289). - # version: [v26.0.1, v25.5.0, v24.0.0] - include: - - version: v26.0.1 - latest: true + version: ${{ fromJson(needs.find-ccm-versions.outputs.versions) }} steps: + - name: Checkout Constellation + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Checkout kubernetes/cloud-provider-gcp uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 with: repository: "kubernetes/cloud-provider-gcp" + path: "cloud-provider-gcp" ref: refs/tags/ccm/${{ matrix.version }} - name: Docker meta @@ -31,33 +77,32 @@ jobs: uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4.6.0 with: images: | - ${{ env.REGISTRY }}/edgelesssys/cloud-provider-gcp + ghcr.io/edgelesssys/cloud-provider-gcp flavor: | - latest=${{ matrix.latest || false }} + latest=${{ matrix.version == needs.find-ccm-versions.outputs.latest }} tags: | type=semver,pattern=v{{version}},value=${{ matrix.version }} - type=semver,pattern=v{{major}}.{{minor}},value=${{ matrix.version }} - type=semver,pattern=v{{major}},value=${{ matrix.version }} - name: Log in to the Container registry id: docker-login uses: ./.github/actions/container_registry_login with: - registry: ${{ env.REGISTRY }} + registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build CCM + working-directory: cloud-provider-gcp run: | bazel build //cmd/cloud-controller-manager:cloud-controller-manager - name: Copy CCM + working-directory: cloud-provider-gcp run: | - # support new and old bazel output paths - cp ./bazel-bin/cmd/cloud-controller-manager/cloud-controller-manager_/cloud-controller-manager ./cloud-controller-manager || \ - cp ./bazel-bin/cmd/cloud-controller-manager/linux_amd64_pure_stripped/cloud-controller-manager ./cloud-controller-manager + cp ./bazel-bin/cmd/cloud-controller-manager/cloud-controller-manager_/cloud-controller-manager ./cloud-controller-manager - name: Prepare Dockerfile + working-directory: cloud-provider-gcp run: | cat > Dockerfile <