From c89e82175d81fdbff1b1e63822ac95818213de3f Mon Sep 17 00:00:00 2001 From: Neha Oudin Date: Thu, 16 Apr 2026 18:13:40 +0200 Subject: [PATCH 1/2] feat: Workflow to call airflow --- .github/workflows/promote.yaml | 95 ++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 .github/workflows/promote.yaml diff --git a/.github/workflows/promote.yaml b/.github/workflows/promote.yaml new file mode 100644 index 0000000000..8eba7cc5e7 --- /dev/null +++ b/.github/workflows/promote.yaml @@ -0,0 +1,95 @@ +# Copyright 2026 Canonical Ltd. +# See LICENSE file for licensing details. +name: Release to candidate promotion train + +on: + workflow_dispatch: + inputs: + mongodb: + description: JSON mapping architecture to revision for MongoDB VM + required: true + type: string + mongos: + description: JSON mapping architecture to revision for Mongos VM + required: true + type: string + mongodb-k8s: + description: JSON mapping architecture to revision for MongoDB K8S VM + required: true + type: string + mongos-k8s: + description: JSON mapping architecture to revision for Mongos K8S VM + required: true + type: string + +jobs: + trigger-release-ci: + # only on beta promotion + name: Trigger release CI (Airflow) + runs-on: ubuntu-latest + steps: + - name: Build JSON Document + id: build-json + shell: python + env: + MONGODB: ${{ inputs.mongodb }} + MONGOS: ${{ inputs.mongos }} + MONGODB_K8S: ${{ inputs.mongodb-k8s }} + MONGOS_K8S: ${{ inputs.mongos-k8s }} + run: | + import json + import os + import sys + output = {} + ARCHITECTURES = ("amd64", "arm64") + + for name, input in [ + ("mongodb", os.environ["MONGODB"]), + ("mongos", os.environ["MONGOS"]), + ("mongodb-k8s", os.environ["MONGODB_K8S"]), + ("mongos-k8s", os.environ["MONGOS_K8S"]), + ]: + try: + data = json.loads(input) + except Exception: + print(f"Invalid data for {name}: {input} (Impossible to JSON decode)") + sys.exit(1) + if not isinstance(data, dict): + print(f"Invalid data for {name}: {data} (Not a dictionary)") + sys.exit(1) + if any(data.get(arch, None) is None for arch in ARCHITECTURES): + print(f"Invalid data for {name}: {data} (Missing architecture)") + sys.exit(1) + output[name] = data + + full_output = f"charms={json.dumps(output)}" + print(f"Computed output: {full_output}") + + with open(os.environ["GITHUB_OUTPUT"], "a") as file: + file.write(full_output) + + - name: Trigger Airflow DAG + run: | + #shellcheck disable=SC2016 + response=$(curl -s -w "\n%{http_code}" -X POST \ + 'https://airflow.data-platform.ps7.canonical.com/api/v2/dags/mongodb_8/dagRuns' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer ${{ secrets.AIRFLOW_API_TOKEN }}' \ + -d '{ + "dag_run_id": "promote-${{ github.run_id }}", + "logical_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", + "conf": { + "charms": ${{ steps.build-json.outputs.charms }} + } + }') + http_code=$(echo "$response" | tail -n1) + body=$(echo "$response" | sed '$d') + echo "$body" + if echo "$body" | grep -q '"detail":"Token Expired"'; then + echo "::error::Airflow API token has expired" + exit 1 + fi + if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then + echo "::error::Airflow API request failed with status $http_code" + exit 1 + fi From fcf094f81a9e96076a7face023f6f9ac83671de3 Mon Sep 17 00:00:00 2001 From: Neha Oudin Date: Sat, 25 Apr 2026 09:22:40 +0200 Subject: [PATCH 2/2] feat: Use pip package version instead of charm revisions --- .github/workflows/promote.yaml | 89 ++++++++++++++-------------------- 1 file changed, 37 insertions(+), 52 deletions(-) diff --git a/.github/workflows/promote.yaml b/.github/workflows/promote.yaml index 8eba7cc5e7..c3bbd594d7 100644 --- a/.github/workflows/promote.yaml +++ b/.github/workflows/promote.yaml @@ -5,20 +5,8 @@ name: Release to candidate promotion train on: workflow_dispatch: inputs: - mongodb: - description: JSON mapping architecture to revision for MongoDB VM - required: true - type: string - mongos: - description: JSON mapping architecture to revision for Mongos VM - required: true - type: string - mongodb-k8s: - description: JSON mapping architecture to revision for MongoDB K8S VM - required: true - type: string - mongos-k8s: - description: JSON mapping architecture to revision for Mongos K8S VM + single-kernel-version: + description: "A pip package version of single kernel (eg: 1.8.42)" required: true type: string @@ -28,60 +16,57 @@ jobs: name: Trigger release CI (Airflow) runs-on: ubuntu-latest steps: - - name: Build JSON Document - id: build-json + - name: Validate input + id: validate-input shell: python env: - MONGODB: ${{ inputs.mongodb }} - MONGOS: ${{ inputs.mongos }} - MONGODB_K8S: ${{ inputs.mongodb-k8s }} - MONGOS_K8S: ${{ inputs.mongos-k8s }} + PIP_VERSION: ${{ inputs.single-kernel-version }} run: | - import json + import re import os - import sys - output = {} - ARCHITECTURES = ("amd64", "arm64") - for name, input in [ - ("mongodb", os.environ["MONGODB"]), - ("mongos", os.environ["MONGOS"]), - ("mongodb-k8s", os.environ["MONGODB_K8S"]), - ("mongos-k8s", os.environ["MONGOS_K8S"]), - ]: - try: - data = json.loads(input) - except Exception: - print(f"Invalid data for {name}: {input} (Impossible to JSON decode)") - sys.exit(1) - if not isinstance(data, dict): - print(f"Invalid data for {name}: {data} (Not a dictionary)") - sys.exit(1) - if any(data.get(arch, None) is None for arch in ARCHITECTURES): - print(f"Invalid data for {name}: {data} (Missing architecture)") - sys.exit(1) - output[name] = data + pip_package_version = os.environ["PIP_VERSION"] + VERSION_REGEX = re.compile(r"\d.\d.\d+") - full_output = f"charms={json.dumps(output)}" - print(f"Computed output: {full_output}") + if not VERSION_REGEX.match(pip_package_version): + raise ValueError(f"Invalid version received: {pip_package_version}") + - name: Check version exists + id: check-version + env: + PIP_VERSION: ${{ inputs.single-kernel-version }} + run: | + set -euo pipefail + DEP_NAME="mongo-charms-single-kernel" + URL="https://pypi.org/pypi/${DEP_NAME}/${PIP_VERSION}/json" + for i in {1..30}; do + if curl -fsS "$URL" >/dev/null; then + echo "Found ${DEP_NAME}==${VERSION_NUMBER} on PyPI." + exit 0 + fi + echo "Maybe transient error (attempt $i/30). Sleeping..." + sleep 60 + done - with open(os.environ["GITHUB_OUTPUT"], "a") as file: - file.write(full_output) + echo "Timed out waiting for ${DEP_NAME}==${PIP_VERSION} on PyPI." + echo "Is the revision available on PyPI ?" + exit 1 - name: Trigger Airflow DAG + env: + PIP_VERSION: ${{ inputs.single-kernel-version }} run: | #shellcheck disable=SC2016 response=$(curl -s -w "\n%{http_code}" -X POST \ 'https://airflow.data-platform.ps7.canonical.com/api/v2/dags/mongodb_8/dagRuns' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ${{ secrets.AIRFLOW_API_TOKEN }}' \ - -d '{ - "dag_run_id": "promote-${{ github.run_id }}", - "logical_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", - "conf": { - "charms": ${{ steps.build-json.outputs.charms }} + -d "{ + \"dag_run_id\": \"promote-${{ github.run_id }}\", + \"logical_date\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\", + \"conf\": { + \"pip_version\": \"${PIP_VERSION}\" } - }') + }") http_code=$(echo "$response" | tail -n1) body=$(echo "$response" | sed '$d') echo "$body"