diff --git a/.github/ISSUE_TEMPLATE/bug.yaml b/.github/ISSUE_TEMPLATE/bug.yaml new file mode 100644 index 0000000..6806de2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yaml @@ -0,0 +1,57 @@ +name: Bug Report +description: File a bug report +labels: ["bug"] +body: + - type: markdown + attributes: + value: > + Thanks for taking the time to fill out this bug report! Before submitting your issue, please make + sure you are using the latest version of the charms. If not, please switch to the newest revision prior to + posting your report to make sure it's not already solved. + - type: textarea + id: bug-description + attributes: + label: Bug Description + description: > + If applicable, add screenshots to help explain your problem. If applicable, add screenshots to + help explain the problem you are facing. + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: To Reproduce + description: > + Please provide a step-by-step instruction of how to reproduce the behavior. + placeholder: | + 1. `juju deploy ...` + 2. `juju relate ...` + 3. `juju status --relations` + validations: + required: true + - type: textarea + id: environment + attributes: + label: Environment + description: > + We need to know a bit more about the context in which you run the charm. + - Are you running Juju locally, on lxd, in multipass or on some other platform? + - What track and channel you deployed the charm from (ie. `latest/edge` or similar). + - Version of any applicable components, like the juju snap, the model controller, lxd, microk8s, and/or multipass. + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant Log Output + description: > + Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + Fetch the logs using `juju debug-log --replay` and `kubectl logs ...`. Additional details available in the juju docs + at https://juju.is/docs/olm/juju-logs + render: shell + validations: + required: true + - type: textarea + id: additional-context + attributes: + label: Additional Context diff --git a/.github/ISSUE_TEMPLATE/task.yaml b/.github/ISSUE_TEMPLATE/task.yaml new file mode 100644 index 0000000..feafd50 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/task.yaml @@ -0,0 +1,44 @@ +name: Task +description: File an enhancement proposal +labels: "enhancement" +body: + - type: markdown + attributes: + value: > + Thanks for taking the time to fill out this enhancement + proposal! Before submitting your issue, please make sure there + isn't already a prior issue concerning this. If there is, + please join that discussion instead. + - type: textarea + id: enhancement-proposal-context + attributes: + label: Context + description: > + Describe why we should work on this task/enhancement, as well as + existing context we should be aware of + validations: + required: true + - type: textarea + id: enhancement-proposal-what + attributes: + label: What needs to get done + description: > + Describe what needs to get done + placeholder: | + 1. Look into X + 2. Implement Y + 3. Create file Z + validations: + required: true + - type: textarea + id: enhancement-proposal-dod + attributes: + label: Definition of Done + description: > + What are the requirements for the task to be considered done + placeholder: | + 1. We know how X works (spike) + 2. Code is doing Y + 3. Charm has functionality Z + validations: + required: true diff --git a/.github/workflows/get-charm-paths.sh b/.github/workflows/get-charm-paths.sh new file mode 100644 index 0000000..1110d59 --- /dev/null +++ b/.github/workflows/get-charm-paths.sh @@ -0,0 +1,30 @@ +#!/bin/bash -x + +# Finds the charms in this repo, outputting them as JSON +# Will return one of: +# * the relative paths of the directories listed in `./charms`, if that directory exists +# * "./", if the root directory has a "metadata.yaml" file +# * otherwise, error +# +# Modified from: https://stackoverflow.com/questions/63517732/github-actions-build-matrix-for-lambda-functions/63736071#63736071 +CHARMS_DIR="./charms" +if [ -d "$CHARMS_DIR" ]; +then + CHARM_PATHS=$(find $CHARMS_DIR -maxdepth 1 -type d -not -path '*/\.*' -not -path "$CHARMS_DIR") +else + if [ -f "./metadata.yaml" ] + then + CHARM_PATHS="./" + else + echo "Cannot find valid charm directories - aborting" + exit 1 + fi +fi + +# Convert output to JSON string format +# { charm_paths: [...] } +CHARM_PATHS_LIST=$(echo "$CHARM_PATHS" | jq -c --slurp --raw-input 'split("\n")[:-1]') + +echo "Found CHARM_PATHS_LIST: $CHARM_PATHS_LIST" + +echo "::set-output name=CHARM_PATHS_LIST::$CHARM_PATHS_LIST" diff --git a/.github/workflows/integrate.yaml b/.github/workflows/integrate.yaml new file mode 100644 index 0000000..6bb27ae --- /dev/null +++ b/.github/workflows/integrate.yaml @@ -0,0 +1,102 @@ +# reusable workflow triggered by other actions +name: CI + +on: + workflow_call: + secrets: + charmcraft-credentials: + required: true + +jobs: + + lib-check: + name: Check libraries + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Check libs + uses: canonical/charming-actions/check-libraries@2.3.0 + with: + credentials: "${{ secrets.charmcraft-credentials }}" + github-token: "${{ secrets.GITHUB_TOKEN }}" + + lint: + name: Lint Check + runs-on: ubuntu-20.04 + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Install dependencies + run: sudo apt-get install python3-pip tox + + - name: Lint code + run: tox -e lint + + unit: + name: Unit Test + runs-on: ubuntu-20.04 + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Install dependencies + run: sudo apt-get install python3-pip tox + + - name: Run unit tests + run: tox -e unit + + terraform-checks: + name: Terraform + uses: canonical/charmed-kubeflow-workflows/.github/workflows/terraform-checks.yaml@main + with: + charm-path: . + # Don't run this workflow since the charm goes to `Error` state when deployed on its own + # See: https://github.com/canonical/resource-dispatcher/issues/66 + apply: false + + integration: + name: Integration Test (build and deploy) + runs-on: ubuntu-20.04 + + steps: + - name: Check out repo + uses: actions/checkout@v4 + + - name: Setup operator environment + uses: charmed-kubernetes/actions-operator@main + with: + provider: microk8s + channel: 1.29-strict/stable + juju-channel: 3.4/stable + microk8s-addons: "dns storage rbac metallb:10.64.140.43-10.64.140.49" + + - name: Run integration tests + run: tox -vve integration -- --model testing + + # On failure, capture debugging resources + - name: Get all + run: kubectl get all -A + if: failure() + + - name: Get juju status + run: juju status + if: failure() + + - name: Get workload logs + run: kubectl logs --tail 100 -ntesting -lapp.kubernetes.io/name=resource-dispatcher + if: failure() + + - name: Get operator logs + run: kubectl logs --tail 100 -ntesting -loperator.juju.is/name=resource-dispatcher + if: failure() + + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + if: failure() + timeout-minutes: 40 diff --git a/.github/workflows/on_pull_request.yaml b/.github/workflows/on_pull_request.yaml new file mode 100644 index 0000000..3d7eef1 --- /dev/null +++ b/.github/workflows/on_pull_request.yaml @@ -0,0 +1,21 @@ +name: On Pull Request + +# On pull_request, we: +# * always publish to charmhub at latest/edge/branchname +# * always run tests + +on: + pull_request: + +jobs: + + tests: + name: Run Tests + uses: ./.github/workflows/integrate.yaml + secrets: inherit + + # publish runs in parallel with tests, as we always publish in this situation + publish-charm: + name: Publish Charm + uses: ./.github/workflows/publish.yaml + secrets: inherit diff --git a/.github/workflows/on_push.yaml b/.github/workflows/on_push.yaml new file mode 100644 index 0000000..31c42da --- /dev/null +++ b/.github/workflows/on_push.yaml @@ -0,0 +1,28 @@ +name: On Push + +# On push to a "special" branch, we: +# * always publish to charmhub at latest/edge/branchname +# * always run tests +# where a "special" branch is one of main or track/**, as +# by convention these branches are the source for a corresponding +# charmhub edge channel. + +on: + push: + branches: + - main + - track/** + +jobs: + + tests: + name: Run Tests + uses: ./.github/workflows/integrate.yaml + secrets: inherit + + # publish runs in series with tests, and only publishes if tests passes + publish-charm: + name: Publish Charm + needs: tests + uses: ./.github/workflows/publish.yaml + secrets: inherit diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 0000000..bacb3ee --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,94 @@ +# reusable workflow for publishing all charms in this repo +name: Publish + +on: + workflow_call: + inputs: + source_branch: + description: Github branch from this repo to publish. If blank, will use the default branch + default: '' + required: false + type: string + secrets: + CHARMCRAFT_CREDENTIALS: + required: true + workflow_dispatch: + inputs: + destination_channel: + description: CharmHub channel to publish to + required: false + default: 'latest/edge' + type: string + source_branch: + description: Github branch from this repo to publish. If blank, will use the default branch + required: false + default: '' + type: string + +jobs: + get-charm-paths: + name: Generate the Charm Matrix + runs-on: ubuntu-20.04 + outputs: + charm_paths_list: ${{ steps.get-charm-paths.outputs.CHARM_PATHS_LIST }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.source_branch }} + - name: Get paths for all charms in repo + id: get-charm-paths + run: bash .github/workflows/get-charm-paths.sh + + + publish-charm: + name: Publish Charm + runs-on: ubuntu-20.04 + needs: get-charm-paths + strategy: + fail-fast: false + matrix: + charm-path: ${{ fromJson(needs.get-charm-paths.outputs.charm_paths_list) }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.source_branch }} + + - name: Select charmhub channel + uses: canonical/charming-actions/channel@2.6.2 + id: select-channel + if: ${{ inputs.destination_channel == '' }} + + # Combine inputs from different sources to a single canonical value so later steps don't + # need logic for picking the right one + - name: Parse and combine inputs + id: parse-inputs + run: | + # destination_channel + destination_channel="${{ inputs.destination_channel || steps.select-channel.outputs.name }}" + echo "setting output of destination_channel=$destination_channel" + echo "::set-output name=destination_channel::$destination_channel" + + # tag_prefix + # if charm_path = ./ --> tag_prefix = '' (null) + # if charm_path != ./some-charm (eg: a charm in a ./charms dir) --> tag_prefix = 'some-charm' + if [ ${{ matrix.charm-path }} == './' ]; then + tag_prefix='' + else + tag_prefix=$(basename ${{ matrix.charm-path }} ) + fi + echo "setting output of tag_prefix=$tag_prefix" + echo "::set-output name=tag_prefix::$tag_prefix" + + - name: Upload charm to charmhub + uses: canonical/charming-actions/upload-charm@2.6.2 + with: + credentials: ${{ secrets.CHARMCRAFT_CREDENTIALS }} + github-token: ${{ secrets.GITHUB_TOKEN }} + charm-path: ${{ matrix.charm-path }} + channel: ${{ steps.parse-inputs.outputs.destination_channel }} + tag-prefix: ${{ steps.parse-inputs.outputs.tag_prefix }} + charmcraft-channel: latest/candidate diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..b4ae293 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,31 @@ +# reusable workflow triggered manually +name: Release charm to other tracks and channels + +on: + workflow_dispatch: + inputs: + destination-channel: + description: 'Destination Channel' + required: true + origin-channel: + description: 'Origin Channel' + required: true + charm-name: + description: 'Charm subdirectory name' + required: true + +jobs: + promote-charm: + name: Promote charm + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + - name: Release charm to channel + uses: canonical/charming-actions/release-charm@2.6.2 + with: + credentials: ${{ secrets.CHARMCRAFT_CREDENTIALS }} + github-token: ${{ secrets.GITHUB_TOKEN }} + destination-channel: ${{ github.event.inputs.destination-channel }} + origin-channel: ${{ github.event.inputs.origin-channel }} + tag-prefix: ${{ github.event.inputs.charm-name }} + charm-path: charms/${{ github.event.inputs.charm-name}}