From a1177fbb1592875b2a08ac6620ac7031e9924e88 Mon Sep 17 00:00:00 2001 From: Dylan Stephano-Shachter Date: Fri, 5 Jun 2026 16:54:36 +0000 Subject: [PATCH] mono repo support for charms --- .github/workflows/_resolve-charm-paths.yaml | 95 +++++++++++++++++ .github/workflows/charm-promote.yaml | 28 ++++- .github/workflows/charm-pull-request.yaml | 50 +++++++-- .github/workflows/charm-quality-gates.yaml | 38 +++++-- .github/workflows/charm-release.yaml | 111 ++++++++++++++------ .github/workflows/charm-tiobe-scan.yaml | 30 +++++- .github/workflows/charm-update-libs.yaml | 36 ++++++- 7 files changed, 326 insertions(+), 62 deletions(-) create mode 100644 .github/workflows/_resolve-charm-paths.yaml diff --git a/.github/workflows/_resolve-charm-paths.yaml b/.github/workflows/_resolve-charm-paths.yaml new file mode 100644 index 00000000..89050c1b --- /dev/null +++ b/.github/workflows/_resolve-charm-paths.yaml @@ -0,0 +1,95 @@ +name: Resolve Charm Paths + +on: + workflow_call: + inputs: + charm-path: + description: | + Path to the charm. Defaults to the current working directory. + If 'charm-paths' is also provided, 'charm-paths' takes precedence. + default: '.' + required: false + type: string + charm-paths: + description: | + JSON list of charm paths (e.g. '["charms/foo", "charms/bar"]'). + If provided, takes precedence over 'charm-path'. + default: '' + required: false + type: string + filter-by-changes: + description: | + When 'charm-paths' is provided and this is true, only charms with + file changes will be included in the matrix (using dorny/paths-filter). + required: true + type: boolean + outputs: + charm-paths: + description: "JSON list of resolved charm paths" + value: ${{ jobs.resolve.outputs.charm-paths }} + +jobs: + resolve: + name: Resolve charm paths + runs-on: ubuntu-latest + permissions: + pull-requests: read + outputs: + charm-paths: ${{ steps.set-paths.outputs.charm-paths }} + steps: + - name: Checkout repository + if: ${{ inputs.filter-by-changes }} + uses: actions/checkout@v6 + with: + repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} + fetch-depth: 0 + + - name: Resolve effective charm paths + id: resolve + env: + CHARM_PATH: ${{ inputs.charm-path }} + CHARM_PATHS: ${{ inputs.charm-paths }} + run: | + if [[ -n "$CHARM_PATHS" ]]; then + echo "all-paths=$CHARM_PATHS" >> "$GITHUB_OUTPUT" + else + echo "all-paths=[\"$CHARM_PATH\"]" >> "$GITHUB_OUTPUT" + fi + + - name: Generate path filters config + if: ${{ inputs.charm-paths != '' && inputs.filter-by-changes }} + id: generate-filters + env: + CHARM_PATHS: ${{ steps.resolve.outputs.all-paths }} + run: | + filters="" + while IFS= read -r path; do + printf -v filters '%s%s:\n - %s/**\n' "$filters" "$path" "$path" + done < <(echo "$CHARM_PATHS" | jq -r '.[]') + { + echo "filters<> "$GITHUB_OUTPUT" + + - name: Filter by changes + if: ${{ inputs.charm-paths != '' && inputs.filter-by-changes }} + id: filter + uses: dorny/paths-filter@v3 + with: + filters: ${{ steps.generate-filters.outputs.filters }} + + - name: Set final charm paths + id: set-paths + env: + ALL_PATHS: ${{ steps.resolve.outputs.all-paths }} + FILTER_ENABLED: ${{ inputs.charm-paths != '' && inputs.filter-by-changes }} + CHANGED_PATHS: ${{ steps.filter.outputs.changes }} + run: | + if [[ "$FILTER_ENABLED" == "true" && -n "$CHANGED_PATHS" ]]; then + echo "charm-paths=$CHANGED_PATHS" >> "$GITHUB_OUTPUT" + elif [[ "$FILTER_ENABLED" == "true" ]]; then + echo "charm-paths=[]" >> "$GITHUB_OUTPUT" + else + echo "charm-paths=$ALL_PATHS" >> "$GITHUB_OUTPUT" + fi diff --git a/.github/workflows/charm-promote.yaml b/.github/workflows/charm-promote.yaml index 862568a5..2f8de6b3 100644 --- a/.github/workflows/charm-promote.yaml +++ b/.github/workflows/charm-promote.yaml @@ -4,10 +4,20 @@ on: workflow_call: inputs: charm-path: - description: "Path to the charm we want to promote. Defaults to the current working directory." + description: | + Path to the charm we want to promote. Defaults to the current working directory. + If 'charm-paths' is also provided, 'charm-paths' takes precedence and this input is ignored. type: string default: '.' required: false + charm-paths: + description: | + JSON list of charm paths (e.g. '["charms/foo", "charms/bar"]'). + If provided, takes precedence over 'charm-path'. + Each path will be processed as a separate matrix entry. + default: '' + required: false + type: string promotion: type: string required: true @@ -21,9 +31,21 @@ on: required: true jobs: + resolve-charm-paths: + uses: canonical/observability/.github/workflows/_resolve-charm-paths.yaml@v1 + with: + charm-path: ${{ inputs.charm-path }} + charm-paths: ${{ inputs.charm-paths }} + filter-by-changes: false + promote: - name: Promote Charm + name: Promote Charm (${{ matrix.charm-path }}) + needs: [resolve-charm-paths] runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + charm-path: ${{ fromJSON(needs.resolve-charm-paths.outputs.charm-paths) }} steps: - name: Checkout uses: actions/checkout@v6 @@ -53,7 +75,7 @@ jobs: - name: Promote charm env: CHARMCRAFT_AUTH: ${{ secrets.CHARMHUB_TOKEN }} - CHARM_PATH: "${{ inputs.charm-path }}" + CHARM_PATH: "${{ matrix.charm-path }}" run: | # Read the charm name from charmcraft.yaml / metadata.yaml cd "$CHARM_PATH" diff --git a/.github/workflows/charm-pull-request.yaml b/.github/workflows/charm-pull-request.yaml index d1d510fe..e1272c93 100644 --- a/.github/workflows/charm-pull-request.yaml +++ b/.github/workflows/charm-pull-request.yaml @@ -4,10 +4,27 @@ on: workflow_call: inputs: charm-path: - description: "Path to the charm we want to publish. Defaults to the current working directory." + description: | + Path to the charm we want to publish. Defaults to the current working directory. + If 'charm-paths' is also provided, 'charm-paths' takes precedence and this input is ignored. default: '.' required: false type: string + charm-paths: + description: | + JSON list of charm paths (e.g. '["charms/foo", "charms/bar"]'). + If provided, takes precedence over 'charm-path'. + Each path will be processed as a separate matrix entry. + default: '' + required: false + type: string + filter-by-changes: + description: | + When 'charm-paths' is provided and this is true, only charms with + file changes will be included in the matrix (using dorny/paths-filter). + default: true + required: false + type: boolean provider: description: "The provider to choose for either machine or k8s tests ('machine', 'microk8s', or 'k8s')" default: 'k8s' @@ -55,6 +72,13 @@ concurrency: cancel-in-progress: true jobs: + resolve-charm-paths: + uses: canonical/observability/.github/workflows/_resolve-charm-paths.yaml@v1 + with: + charm-path: ${{ inputs.charm-path }} + charm-paths: ${{ inputs.charm-paths }} + filter-by-changes: ${{ inputs.filter-by-changes }} + ci-ignore: name: Check against ignorelist runs-on: ubuntu-latest @@ -89,12 +113,16 @@ jobs: echo "any_modified=${{ steps.changed-files.outputs.any_modified }}" >> "$GITHUB_OUTPUT" lib-check: - name: Check libraries # Check if the charm libraries are updated and add the relevant label to the PR + name: Check libraries (${{ matrix.charm-path }}) # Check if the charm libraries are updated and add the relevant label to the PR runs-on: ubuntu-latest - needs: [ci-ignore] + needs: [resolve-charm-paths, ci-ignore] # NOTE: This job doesn't run on forks, as they wouldn't have the necessary secret to # update the PR labels. - if: ${{ github.event_name == 'pull_request' && needs.ci-ignore.outputs.any_modified == 'true' && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }} + if: ${{ github.event_name == 'pull_request' && needs.resolve-charm-paths.outputs.charm-paths != '[]' && needs.ci-ignore.outputs.any_modified == 'true' && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }} + strategy: + fail-fast: false + matrix: + charm-path: ${{ fromJSON(needs.resolve-charm-paths.outputs.charm-paths) }} steps: - name: Checkout uses: actions/checkout@v6 @@ -110,7 +138,7 @@ jobs: CHARMCRAFT_AUTH: ${{ secrets.CHARMHUB_TOKEN }} PR_NUMBER: ${{ github.event.number }} run: | - cd "${{ inputs.charm-path }}" + cd "${{ matrix.charm-path }}" fetch_lib="$(charmcraft fetch-lib)" # If charm libraries are not up-to-date if echo "$fetch_lib" | grep -qE "not found in Charmhub|updated to version|has local changes"; then @@ -120,18 +148,22 @@ jobs: fi quality-checks: - name: Quality Checks + name: Quality Checks (${{ matrix.charm-path }}) needs: + - resolve-charm-paths - ci-ignore - if: needs.ci-ignore.outputs.any_modified == 'true' + if: ${{ needs.resolve-charm-paths.outputs.charm-paths != '[]' && needs.ci-ignore.outputs.any_modified == 'true' }} + strategy: + fail-fast: false + matrix: + charm-path: ${{ fromJSON(needs.resolve-charm-paths.outputs.charm-paths) }} uses: canonical/observability/.github/workflows/_charm-quality-checks.yaml@v2 secrets: inherit with: - charm-path: ${{ inputs.charm-path }} + charm-path: ${{ matrix.charm-path }} provider: ${{ inputs.provider }} charmcraft-channel: ${{ inputs.charmcraft-channel }} juju-channel: ${{ inputs.juju-channel }} parallelize-integration: ${{ inputs.parallelize-integration }} automatically-retry-hooks: ${{ inputs.automatically-retry-hooks }} enable-integration: ${{ inputs.enable-integration }} - diff --git a/.github/workflows/charm-quality-gates.yaml b/.github/workflows/charm-quality-gates.yaml index 872eab7f..feaa9678 100644 --- a/.github/workflows/charm-quality-gates.yaml +++ b/.github/workflows/charm-quality-gates.yaml @@ -6,9 +6,18 @@ on: charm-path: description: | Path to the charm we want to promote. Defaults to the current working directory. + If 'charm-paths' is also provided, 'charm-paths' takes precedence and this input is ignored. default: '.' required: false type: string + charm-paths: + description: | + JSON list of charm paths (e.g. '["charms/foo", "charms/bar"]'). + If provided, takes precedence over 'charm-path'. + Each path will be processed as a separate matrix entry. + default: '' + required: false + type: string tracks: description: Json list of track names on which to run quality gates. type: string @@ -19,17 +28,25 @@ on: required: true concurrency: - group: quality-gates${{ (inputs.charm-path && inputs.charm-path != '.') && format('-{0}', inputs.charm-path) || '' }} + group: quality-gates-${{ github.ref }}${{ (inputs.charm-path && inputs.charm-path != '.') && format('-{0}', inputs.charm-path) || '' }} cancel-in-progress: true jobs: + resolve-charm-paths: + uses: canonical/observability/.github/workflows/_resolve-charm-paths.yaml@v1 + with: + charm-path: ${{ inputs.charm-path }} + charm-paths: ${{ inputs.charm-paths }} + filter-by-changes: false + quality-gate-edge: - name: Quality gate (edge -> beta) - if: always() + name: Quality gate (edge -> beta) (${{ matrix.charm-path }}) + needs: [resolve-charm-paths] runs-on: ubuntu-latest strategy: fail-fast: false matrix: + charm-path: ${{ fromJSON(needs.resolve-charm-paths.outputs.charm-paths) }} track: ${{ fromJSON(inputs.tracks) }} steps: - name: Checkout @@ -41,18 +58,19 @@ jobs: - name: Get charm name id: get-charm-name run: | - cd "${{ inputs.charm-path }}" + cd "${{ matrix.charm-path }}" charm_name=$(yq .name metadata.yaml 2>/dev/null || yq .name charmcraft.yaml) echo "charm_name=$charm_name" echo "charm_name=$charm_name" >> "$GITHUB_OUTPUT" - name: "Run the quality gates" run: | + cd "${{ matrix.charm-path }}" uvx tox -e qualitygate-beta - name: Promote from edge to beta env: CHARMCRAFT_AUTH: ${{ secrets.CHARMHUB_TOKEN }} CHARM_NAME: ${{ steps.get-charm-name.outputs.charm_name }} - CHARM_PATH: ${{ inputs.charm-path }} + CHARM_PATH: ${{ matrix.charm-path }} TRACK: ${{ matrix.track }} run: | cd "$CHARM_PATH" @@ -61,12 +79,13 @@ jobs: echo "Promoted from edge to beta!" quality-gate-beta: - name: Quality gate (beta -> candidate) - if: always() + name: Quality gate (beta -> candidate) (${{ matrix.charm-path }}) + needs: [resolve-charm-paths] runs-on: ubuntu-latest strategy: fail-fast: false matrix: + charm-path: ${{ fromJSON(needs.resolve-charm-paths.outputs.charm-paths) }} track: ${{ fromJSON(inputs.tracks) }} steps: - name: Checkout @@ -78,18 +97,19 @@ jobs: - name: Get charm name id: get-charm-name run: | - cd "${{ inputs.charm-path }}" + cd "${{ matrix.charm-path }}" charm_name=$(yq .name metadata.yaml 2>/dev/null || yq .name charmcraft.yaml) echo "charm_name=$charm_name" echo "charm_name=$charm_name" >> "$GITHUB_OUTPUT" - name: "Run the quality gates" run: | + cd "${{ matrix.charm-path }}" uvx tox -e qualitygate-candidate - name: Promote from beta to candidate env: CHARMCRAFT_AUTH: ${{ secrets.CHARMHUB_TOKEN }} CHARM_NAME: ${{ steps.get-charm-name.outputs.charm_name }} - CHARM_PATH: ${{ inputs.charm-path }} + CHARM_PATH: ${{ matrix.charm-path }} TRACK: ${{ matrix.track }} run: | cd "$CHARM_PATH" diff --git a/.github/workflows/charm-release.yaml b/.github/workflows/charm-release.yaml index 286b4343..778494ed 100644 --- a/.github/workflows/charm-release.yaml +++ b/.github/workflows/charm-release.yaml @@ -4,10 +4,27 @@ on: workflow_call: inputs: charm-path: - description: "Path to the charm we want to publish. Defaults to the current working directory." + description: | + Path to the charm we want to publish. Defaults to the current working directory. + If 'charm-paths' is also provided, 'charm-paths' takes precedence and this input is ignored. default: '.' required: false type: string + charm-paths: + description: | + JSON list of charm paths (e.g. '["charms/foo", "charms/bar"]'). + If provided, takes precedence over 'charm-path'. + Each path will be processed as a separate matrix entry. + default: '' + required: false + type: string + filter-by-changes: + description: | + When 'charm-paths' is provided and this is true, only charms with + file changes will be included in the matrix (using dorny/paths-filter). + default: true + required: false + type: boolean provider: description: "The provider to choose for either machine or k8s tests ('machine', 'microk8s', or 'k8s')" default: 'k8s' @@ -82,12 +99,18 @@ on: OBSERVABILITY_NOCTUA_TOKEN: required: true - concurrency: - group: release${{ (inputs.charm-path && inputs.charm-path != '.') && format('-{0}', inputs.charm-path) || '' }} + group: release-${{ github.ref }}${{ (inputs.charm-path && inputs.charm-path != '.') && format('-{0}', inputs.charm-path) || '' }} cancel-in-progress: true jobs: + resolve-charm-paths: + uses: canonical/observability/.github/workflows/_resolve-charm-paths.yaml@v1 + with: + charm-path: ${{ inputs.charm-path }} + charm-paths: ${{ inputs.charm-paths }} + filter-by-changes: ${{ inputs.filter-by-changes }} + ci-ignore: name: Check against ignorelist runs-on: ubuntu-latest @@ -131,10 +154,10 @@ jobs: define-matrix: name: Define runner and build matrix runs-on: ubuntu-latest - needs: [ci-ignore] - if: needs.ci-ignore.outputs.any_modified == 'true' + needs: [resolve-charm-paths, ci-ignore] + if: ${{ needs.resolve-charm-paths.outputs.charm-paths != '[]' && needs.ci-ignore.outputs.any_modified == 'true' }} outputs: - runners: ${{ steps.build-matrix.outputs.runners }} + matrix: ${{ steps.build-matrix.outputs.matrix }} release-channel: ${{ steps.define-channel.outputs.release_channel }} steps: - name: Checkout @@ -144,24 +167,28 @@ jobs: sudo snap install yq - name: Define build matrix id: build-matrix + env: + CHARM_PATHS: ${{ needs.resolve-charm-paths.outputs.charm-paths }} run: | - cd "${{ inputs.charm-path }}" - - if [ "${{ inputs.pack-using-remote-build }}" = "true" ]; then - # If using remote build, just use ubuntu-latest - runners='["ubuntu-latest"]' - else - # Normal logic: get runners from charmcraft.yaml - runners="$( \ - yq -o json '.platforms | to_entries | map(.key)' charmcraft.yaml | \ - sed 's/".*amd64.*"/"ubuntu-latest"/' | \ - sed 's/".*arm64.*"/"Ubuntu_ARM64_4C_16G_03"/' | \ - jq -rc 'unique' \ - )" - fi - - echo "runners=$runners" - echo "runners=$runners" >> "$GITHUB_OUTPUT" + matrix="[]" + while IFS= read -r charm_path; do + if [ "${{ inputs.pack-using-remote-build }}" = "true" ]; then + # If using remote build, just use ubuntu-latest + runners='["ubuntu-latest"]' + else + # Normal logic: get runners from charmcraft.yaml + runners="$( \ + cd "$charm_path" && \ + yq -o json '.platforms | to_entries | map(.key)' charmcraft.yaml | \ + sed 's/".*amd64.*"/"ubuntu-latest"/' | \ + sed 's/".*arm64.*"/"Ubuntu_ARM64_4C_16G_03"/' | \ + jq -rc 'unique' \ + )" + fi + matrix="$(echo "$matrix" | jq -rc --arg path "$charm_path" --argjson runners "$runners" '. + [{"charm-path": $path, "runners": $runners}]')" + done < <(echo "$CHARM_PATHS" | jq -r '.[]') + echo "matrix=$matrix" + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" - name: Define release channel id: define-channel env: @@ -177,12 +204,16 @@ jobs: echo "release_channel=$release_channel" >> "$GITHUB_OUTPUT" quality-checks: - name: Quality Checks + name: Quality Checks (${{ matrix.entry.charm-path }}) uses: canonical/observability/.github/workflows/_charm-quality-checks.yaml@v2 needs: [define-matrix] + strategy: + fail-fast: false + matrix: + entry: ${{ fromJSON(needs.define-matrix.outputs.matrix) }} secrets: inherit with: - charm-path: ${{ inputs.charm-path }} + charm-path: ${{ matrix.entry.charm-path }} provider: ${{ inputs.provider }} charmcraft-channel: ${{ inputs.charmcraft-channel }} juju-channel: ${{ inputs.juju-channel }} @@ -191,10 +222,16 @@ jobs: enable-integration: ${{ inputs.enable-integration }} release-charm: - name: Release the charm + name: Release the charm (${{ matrix.entry.charm-path }}) + # NOTE: all-or-nothing — if quality checks fail for any charm, no charms are released. + # This is intentional: partial releases from the same commit are risky. needs: - define-matrix - quality-checks + strategy: + fail-fast: false + matrix: + entry: ${{ fromJSON(needs.define-matrix.outputs.matrix) }} uses: canonical/observability/.github/workflows/_charm-release.yaml@v2 secrets: CHARMHUB_TOKEN: ${{ secrets.CHARMHUB_TOKEN }} @@ -202,16 +239,21 @@ jobs: OBSERVABILITY_NOCTUA_TOKEN: ${{ secrets.OBSERVABILITY_NOCTUA_TOKEN }} with: release-channel: "${{ needs.define-matrix.outputs.release-channel }}" - charm-path: "${{ inputs.charm-path }}" - runners: "${{ needs.define-matrix.outputs.runners }}" + charm-path: "${{ matrix.entry.charm-path }}" + runners: ${{ toJSON(matrix.entry.runners) }} charmcraft-channel: "${{ inputs.charmcraft-channel }}" git-tag-prefix: "${{ inputs.git-tag-prefix }}" pack-using-remote-build: ${{ inputs.pack-using-remote-build }} release-libs: - name: Release any bumped charm library + name: Release any bumped charm library (${{ matrix.charm-path }}) needs: + - resolve-charm-paths - release-charm + strategy: + fail-fast: false + matrix: + charm-path: ${{ fromJSON(needs.resolve-charm-paths.outputs.charm-paths) }} runs-on: ubuntu-latest steps: - name: Checkout the source @@ -222,7 +264,7 @@ jobs: env: CHARMCRAFT_AUTH: "${{ secrets.CHARMHUB_TOKEN }}" CHARMCRAFT_CHANNEL: "${{ inputs.charmcraft-channel }}" - CHARM_PATH: "${{ inputs.charm-path }}" + CHARM_PATH: "${{ matrix.charm-path }}" run: | # Install Charmcraft sudo snap install charmcraft --classic --channel "$CHARMCRAFT_CHANNEL" @@ -246,14 +288,19 @@ jobs: fi release-terraform: - name: Release the Terraform module + name: Release the Terraform module (${{ matrix.charm-path }}) needs: + - resolve-charm-paths - release-charm if: github.ref_name != 'main' && startsWith(github.ref_name, 'track/') + strategy: + fail-fast: false + matrix: + charm-path: ${{ fromJSON(needs.resolve-charm-paths.outputs.charm-paths) }} uses: canonical/observability/.github/workflows/terraform-release.yaml@v2 secrets: OBSERVABILITY_NOCTUA_TOKEN: ${{ secrets.OBSERVABILITY_NOCTUA_TOKEN }} with: terraform-tag-prefix: "${{ inputs.terraform-tag-prefix }}" terraform-tag-suffix: "${{ inputs.terraform-tag-suffix }}" - terraform-path: "${{ inputs.charm-path }}/terraform" + terraform-path: "${{ matrix.charm-path }}/terraform" diff --git a/.github/workflows/charm-tiobe-scan.yaml b/.github/workflows/charm-tiobe-scan.yaml index 951a6c79..9e1e4da7 100644 --- a/.github/workflows/charm-tiobe-scan.yaml +++ b/.github/workflows/charm-tiobe-scan.yaml @@ -7,10 +7,20 @@ on: workflow_call: inputs: charm-path: - description: "Path to the command runner that runs unit tests and produces coverage. Defaults to the current working directory." + description: | + Path to the command runner that runs unit tests and produces coverage. Defaults to the current working directory. + If 'charm-paths' is also provided, 'charm-paths' takes precedence and this input is ignored. default: '.' required: false type: string + charm-paths: + description: | + JSON list of charm paths (e.g. '["charms/foo", "charms/bar"]'). + If provided, takes precedence over 'charm-path'. + Each path will be processed as a separate matrix entry. + default: '' + required: false + type: string lockfile-path: description: "Path to the lockfile folder (or requirements.txt). Useful for monorepos, where the root doesn't have a lockfile. If empty, `charm-path` is used." default: "" @@ -28,10 +38,22 @@ on: type: string jobs: + resolve-charm-paths: + uses: canonical/observability/.github/workflows/_resolve-charm-paths.yaml@v1 + with: + charm-path: ${{ inputs.charm-path }} + charm-paths: ${{ inputs.charm-paths }} + filter-by-changes: false + scan: - name: Scan and upload + name: Scan and upload (${{ matrix.charm-path }}) + needs: [resolve-charm-paths] runs-on: [self-hosted, linux, amd64, tiobe, jammy] timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + charm-path: ${{ fromJSON(needs.resolve-charm-paths.outputs.charm-paths) }} steps: - name: Checkout the project uses: actions/checkout@v6 @@ -48,7 +70,7 @@ jobs: - name: Generate unittest coverage report env: - CHARM_PATH: ${{ inputs.charm-path }} + CHARM_PATH: ${{ matrix.charm-path }} COVERAGE_FOLDER: ${{ inputs.coverage-folder }} run: | base_wd="$(pwd)" @@ -57,7 +79,7 @@ jobs: - name: Activate and prepare Python virtual environment env: - CHARM_PATH: ${{ inputs.charm-path }} + CHARM_PATH: ${{ matrix.charm-path }} LOCKFILE_PATH: ${{ inputs.lockfile-path }} run: | # Use LOCKFILE_PATH (if not empty) to create the virtual environment, otherwise use CHARM_PATH diff --git a/.github/workflows/charm-update-libs.yaml b/.github/workflows/charm-update-libs.yaml index aaebee67..26bd5c4d 100644 --- a/.github/workflows/charm-update-libs.yaml +++ b/.github/workflows/charm-update-libs.yaml @@ -3,10 +3,20 @@ on: workflow_call: inputs: charm-path: - description: "Path to the charm we want to publish. Defaults to the current working directory." + description: | + Path to the charm we want to publish. Defaults to the current working directory. + If 'charm-paths' is also provided, 'charm-paths' takes precedence and this input is ignored. default: "." required: false type: string + charm-paths: + description: | + JSON list of charm paths (e.g. '["charms/foo", "charms/bar"]'). + If provided, takes precedence over 'charm-path'. + Each path will be processed as a separate matrix entry. + default: '' + required: false + type: string git-branch: description: "Branch name for the charm library update. Defaults to 'chore/auto-libs'." default: "chore/auto-libs" @@ -38,12 +48,28 @@ on: NOCTUA_GPG_PRIVATE: required: true +permissions: + contents: write + pull-requests: write + jobs: + resolve-charm-paths: + uses: canonical/observability/.github/workflows/_resolve-charm-paths.yaml@v1 + with: + charm-path: ${{ inputs.charm-path }} + charm-paths: ${{ inputs.charm-paths }} + filter-by-changes: false + update-lib: - name: Check libraries + name: Check libraries (${{ matrix.charm-path }}) + needs: [resolve-charm-paths] runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + charm-path: ${{ fromJSON(needs.resolve-charm-paths.outputs.charm-paths) }} env: - GIT_BRANCH: ${{ inputs.git-branch }} + GIT_BRANCH: ${{ inputs.git-branch }}/${{ matrix.charm-path }} steps: - name: Checkout uses: actions/checkout@v6 @@ -70,7 +96,7 @@ jobs: - name: Check for major library updates run: | sudo snap install charmcraft --classic --channel "${{ inputs.charmcraft-channel }}" - cd "$GITHUB_WORKSPACE/${{ inputs.charm-path }}" + cd "$GITHUB_WORKSPACE/${{ matrix.charm-path }}" # Get the charm name charm_name=$( (yq .name metadata.yaml 2>/dev/null || yq .name charmcraft.yaml) | tr - _) if [[ $charm_name = "" ]]; then echo "Error: can't extract the charm name." && exit 1; fi @@ -121,7 +147,7 @@ jobs: - name: Fetch charm libraries run: | git pull - cd "$GITHUB_WORKSPACE/${{ inputs.charm-path }}" + cd "$GITHUB_WORKSPACE/${{ matrix.charm-path }}" charmcraft fetch-lib env: CHARMCRAFT_AUTH: "${{ secrets.CHARMHUB_TOKEN }}"