Publishing and promoting #70
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright 2024 Canonical Ltd. | |
# See LICENSE file for licensing details. | |
name: Publish charm | |
on: | |
push: | |
branches: | |
- main | |
pull_request: | |
env: | |
OWNER: ${{ github.repository_owner }} | |
REGISTRY: ghcr.io | |
channel: latest/edge | |
charm_directory: "charm" | |
charmcraft_ref: feat-12f-django | |
charmcraft_repository: weiiwang01/charmcraft | |
paas_app_charmer_oci_name: django-app-image | |
tag_prefix: | |
working_directory: "./" | |
jobs: | |
branch-up-to-date-check-enabled: | |
runs-on: ubuntu-22.04 | |
steps: | |
- uses: octokit/[email protected] | |
id: get-branch-protection | |
env: | |
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} | |
with: | |
route: GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks | |
repo: ${{ github.event.repository.name }} | |
owner: ${{ github.event.repository.owner.login }} | |
branch: main | |
- run: | | |
if [ ${{ fromJson(steps.get-branch-protection.outputs.data).strict }} != "true" ]; then | |
echo "::error::Strict checks are not enabled for this repository" | |
exit 1 | |
fi | |
draft-publish-docs: | |
name: Draft publish docs | |
needs: [ branch-up-to-date-check-enabled ] | |
runs-on: ubuntu-22.04 | |
defaults: | |
run: | |
working-directory: ${{ env.working_directory }}/${{ env.charm_directory }} | |
steps: | |
- uses: actions/[email protected] | |
- name: Search for docs folder | |
id: docs-exist | |
run: echo "docs_exist=$([[ -d docs ]] && echo 'True' || echo 'False')" >> $GITHUB_OUTPUT | |
- name: Publish documentation | |
if: steps.docs-exist.outputs.docs_exist == 'True' | |
uses: canonical/discourse-gatekeeper@stable | |
with: | |
discourse_host: discourse.charmhub.io | |
discourse_api_username: ${{ secrets.DISCOURSE_API_USERNAME }} | |
discourse_api_key: ${{ secrets.DISCOURSE_API_KEY }} | |
dry_run: true | |
github_token: ${{ secrets.GITHUB_TOKEN }} | |
charm_dir: ${{ env.working_directory }}/${{ env.charm_directory }} | |
vars: | |
runs-on: ubuntu-22.04 | |
outputs: | |
charm_working_directory: ${{ env.working_directory }}/${{ env.charm_directory }} | |
channel: ${{ env.channel }} | |
steps: | |
- run: echo "Exposing env vars" | |
get-runner-image: | |
name: Get runner image | |
needs: vars | |
uses: canonical/operator-workflows/.github/workflows/get_runner_image.yaml@test-netbox | |
with: | |
working-directory: ${{ needs.vars.outputs.charm_working_directory }} | |
secrets: inherit | |
release-charm-libs: | |
name: Release charm libs | |
needs: [ branch-up-to-date-check-enabled ] | |
runs-on: ubuntu-22.04 | |
steps: | |
- uses: actions/[email protected] | |
- if: ${{ env.working_directory }}/${{ env.charm_directory }} != './/.' | |
name: Change directory | |
run: | | |
TEMP_DIR=$(mktemp -d) | |
cp -rp ./${{ env.working_directory }}/${{ env.charm_directory }}/. $TEMP_DIR | |
rm -rf .* * || : | |
cp -rp $TEMP_DIR/. . | |
rm -rf $TEMP_DIR | |
- uses: canonical/charming-actions/[email protected] | |
name: Release libs | |
with: | |
credentials: ${{ secrets.CHARMHUB_TOKEN }} | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
get-run-id: | |
name: Get workflow run id | |
needs: [ branch-up-to-date-check-enabled ] | |
runs-on: ubuntu-22.04 | |
outputs: | |
run-id: ${{ env.RUN_ID }} | |
steps: | |
- name: Get workflow run id | |
# TODO if: ${{ github.event_name == 'push' }} | |
if: false | |
shell: bash | |
run: | | |
# Get commit info | |
TREE_SHA=$(gh api \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
/repos/${{ github.repository }}/commits/${GITHUB_SHA} \ | |
--jq '.commit.tree.sha') | |
# Get workflow run id from this specific tree id, paginate until found | |
TOTAL_COUNT=$(gh api \ | |
--method GET \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
/repos/${{ github.repository }}/actions/runs \ | |
-f status=completed \ | |
-f event=pull_request | jq ".total_count") | |
PER_PAGE=100 | |
MAX_PAGES=$(( (TOTAL_COUNT + 99) / $PER_PAGE )) | |
PAGE=1 | |
while true; do | |
RESULT=$( gh api \ | |
--method GET \ | |
-H "Accept: application/vnd.github+json" \ | |
-H "X-GitHub-Api-Version: 2022-11-28" \ | |
/repos/${{ github.repository }}/actions/runs \ | |
-f page=$PAGE \ | |
-f per_page=$PER_PAGE \ | |
-f status=completed \ | |
-f event=pull_request \ | |
--jq "[ | |
.workflow_runs[] | |
| select(.path == \".github/workflows/integration_test.yaml\") | |
| select(.head_commit.tree_id == \"$TREE_SHA\") | |
] | max_by(.updated_at) | .id" | |
) | |
if [[ -n $RESULT ]]; then | |
RUN_ID=$RESULT | |
break | |
fi | |
if [[ "PAGE" -eq "$MAX_PAGES" ]]; then | |
echo "::error::No workflow run id found for specific tree id" | |
exit 1 | |
fi | |
((PAGE++)) | |
done | |
echo "RUN_ID=$RUN_ID" >> $GITHUB_ENV | |
env: | |
GITHUB_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} | |
- name: Get current run id | |
# TODO if: ${{ github.event_name == 'pull_request' }} | |
if: false | |
shell: bash | |
run: | | |
echo "RUN_ID=${{ github.run_id }}" >> $GITHUB_ENV | |
- name: Get current run id TODO remove | |
shell: bash | |
run: | | |
echo "RUN_ID=8601127083" >> $GITHUB_ENV | |
get-images: | |
name: Get images | |
runs-on: ubuntu-22.04 | |
outputs: | |
images: ${{ env.IMAGES }} | |
steps: | |
- uses: actions/[email protected] | |
- name: Get images | |
working-directory: ${{ env.working_directory }} | |
run: | | |
lines=$(find . -type f -name rockcraft.yaml | wc -l) | |
if [ $lines -ne 0 ]; then | |
IMAGES=$(find . -type f -name rockcraft.yaml | xargs -l yq '.name' | jq -Rsc '. / "\n" - [""]') | |
else | |
IMAGES=$(ls *.Dockerfile 2> /dev/null | sed s/\.Dockerfile// | jq -Rsc '. / "\n" - [""]') | |
fi | |
echo "IMAGES=$IMAGES" >> $GITHUB_ENV | |
publish-images: | |
name: Publish images to charmhub | |
runs-on: ${{ needs.get-runner-image.outputs.runs-on }} | |
needs: [ get-images, get-run-id, get-runner-image] | |
if: ${{ needs.get-images.outputs.images != '[]' }} | |
steps: | |
- uses: actions/checkout@v4 | |
if: env.charmcraft_repository != '' | |
with: | |
repository: ${{ env.charmcraft_repository }} | |
ref: ${{ env.charmcraft_ref }} | |
path: ./charmcraft | |
fetch-depth: 0 | |
- name: Get Charmcraft SHA | |
if: env.charmcraft_repository != '' | |
id: charmcraft-sha | |
working-directory: ./charmcraft | |
run: echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT | |
- name: Restore Charmcraft Cache | |
if: env.charmcraft_repository != '' | |
id: restore-charmcraft | |
uses: actions/cache/restore@v4 | |
with: | |
path: ./charmcraft*.snap | |
key: charmcraft-${{ steps.charmcraft-sha.outputs.sha }} | |
- name: Install Snapcraft | |
if: steps.restore-charmcraft.outputs.cache-hit != 'true' && env.charmcraft_repository != '' | |
run: sudo snap install snapcraft --classic | |
- name: Build Charmcraft | |
if: steps.restore-charmcraft.outputs.cache-hit != 'true' && env.charmcraft_repository != '' | |
working-directory: ./charmcraft | |
run: | | |
snapcraft --use-lxd | |
cp charmcraft*.snap ../ | |
- name: Save Charmcraft Cache | |
uses: actions/cache/save@v4 | |
if: steps.restore-charmcraft.outputs.cache-hit != 'true' && env.charmcraft_repository != '' | |
with: | |
path: ./charmcraft*.snap | |
key: ${{ steps.restore-charmcraft.outputs.cache-primary-key }} | |
- name: Install charmcraft | |
if: env.charmcraft_repository != '' | |
run: sudo snap install --dangerous --classic charmcraft*.snap | |
- name: Clean up | |
if: env.charmcraft_repository != '' | |
run: rm -rf * | |
- name: Install charmcraft | |
if: env.charmcraft_repository == '' | |
run: | | |
sudo snap install charmcraft --classic --channel ${{ env.charmcraft_channel }} | |
- uses: actions/[email protected] | |
- if: ${{ env.working_directory }}/${{ env.charm_directory }} != './/.' | |
name: Change directory | |
run: | | |
TEMP_DIR=$(mktemp -d) | |
cp -rp ./${{ env.working_directory }}/${{ env.charm_directory }}/. $TEMP_DIR | |
rm -rf .* * || : | |
cp -rp $TEMP_DIR/. . | |
rm -rf $TEMP_DIR | |
- name: Get charm name | |
id: get-charm-name | |
run: | | |
CHARM_NAME="$([ -f metadata.yaml ] && yq '.name' metadata.yaml || echo UNKNOWN)" | |
if [ "$CHARM_NAME" == "UNKNOWN" ]; then | |
CHARM_NAME="$([ -f charmcraft.yaml ] && yq '.name' charmcraft.yaml || echo UNKNOWN)" | |
fi | |
echo "CHARM_NAME=$CHARM_NAME">> $GITHUB_ENV | |
- name: Log in to the Container registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Download images artifact | |
# TODO if: ${{ github.event_name == 'push' }} | |
if: true | |
run: | | |
gh run download ${{ needs.get-run-id.outputs.run-id }} -R ${{ github.repository }} -n ${{ env.CHARM_NAME }}-images | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Download images artifact (for testing) | |
uses: actions/download-artifact@v4 | |
# TODO if: ${{ github.event_name == 'pull_request' }} | |
if: false | |
with: | |
name: ${{ env.CHARM_NAME }}-images | |
- name: Publish image | |
env: | |
CHARMCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "true" | |
CHARMCRAFT_AUTH: ${{ secrets.CHARMHUB_TOKEN }} | |
run: | | |
charm=${{ env.CHARM_NAME }} | |
declare -a resources | |
declare -a images | |
if [ -f metadata.yaml ]; then | |
for resource in $(yq -er '.resources | with_entries(select(.value.type=="oci-image")) | keys | join(" ")' metadata.yaml); do | |
resources+=("$resource") | |
done | |
else | |
for resource in $(yq -er '.resources | with_entries(select(.value.type=="oci-image")) | keys | join(" ")' <(charmcraft expand-extensions)); do | |
resources+=("$resource") | |
done | |
fi | |
for image in $(cat ${{ env.CHARM_NAME }}-images); do | |
images+=("$image") | |
done | |
echo resources: -"${resources[@]}"- | |
echo images: -"${images[@]}"- | |
for image in "${images[@]}"; do | |
if [[ "${{ env.paas_app_charmer_oci_name }}" != "" ]]; then | |
# This is for paas-app-charmer . The main image name (resource oci in charmcraft.yaml) is | |
# defined with the env variable paas-app-charmer-oci-name, and corresponds to the main | |
# image in rockcraft.yaml. | |
resource_name="{{ env.paas_app_charmer_oci_name }}" | |
else | |
resource_name=$(echo $image | awk -F '/' '{print $NF}' | cut -d ':' -f 1)-image | |
fi | |
if [[ " ${resources[@]} " =~ " $resource " ]]; then | |
docker pull $image | |
image_id=$(docker images $image --format "{{.ID}}") | |
charmcraft upload-resource $charm $resource --image=$image_id --verbosity=brief | |
fi | |
done | |
publish-charm: | |
name: Publish charm | |
runs-on: ${{ needs.get-runner-image.outputs.runs-on }} | |
needs: [get-run-id, get-runner-image, publish-images, vars] | |
if: ${{ !failure() }} | |
steps: | |
- uses: actions/checkout@v4 | |
if: env.charmcraft_repository != '' | |
with: | |
repository: ${{ env.charmcraft_repository }} | |
ref: ${{ env.charmcraft_ref }} | |
path: ./charmcraft | |
fetch-depth: 0 | |
- name: Get Charmcraft SHA | |
if: env.charmcraft_repository != '' | |
id: charmcraft-sha | |
working-directory: ./charmcraft | |
run: echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT | |
- name: Restore Charmcraft Cache | |
if: env.charmcraft_repository != '' | |
id: restore-charmcraft | |
uses: actions/cache/restore@v4 | |
with: | |
path: ./charmcraft*.snap | |
key: charmcraft-${{ steps.charmcraft-sha.outputs.sha }} | |
- name: Install Snapcraft | |
if: steps.restore-charmcraft.outputs.cache-hit != 'true' && env.charmcraft_repository != '' | |
run: sudo snap install snapcraft --classic | |
- name: Build Charmcraft | |
if: steps.restore-charmcraft.outputs.cache-hit != 'true' && env.charmcraft_repository != '' | |
working-directory: ./charmcraft | |
run: | | |
snapcraft --use-lxd | |
cp charmcraft*.snap ../ | |
- name: Save Charmcraft Cache | |
uses: actions/cache/save@v4 | |
if: steps.restore-charmcraft.outputs.cache-hit != 'true' && env.charmcraft_repository != '' | |
with: | |
path: ./charmcraft*.snap | |
key: ${{ steps.restore-charmcraft.outputs.cache-primary-key }} | |
- name: Install charmcraft | |
if: env.charmcraft_repository != '' | |
run: sudo snap install --dangerous --classic charmcraft*.snap | |
- name: Clean up | |
if: env.charmcraft_repository != '' | |
run: rm -rf * | |
- name: Install charmcraft | |
if: env.charmcraft_repository == '' | |
run: | | |
sudo snap install charmcraft --classic --channel ${{ env.charmcraft_channel }} | |
- uses: actions/[email protected] | |
- if: ${{ env.working_directory }}/${{ env.charm_directory }} != './/.' | |
name: Change directory | |
run: | | |
set -x | |
ls | |
TEMP_DIR=$(mktemp -d) | |
cp -rp ./${{ env.working_directory }}/${{ env.charm_directory }}/. $TEMP_DIR | |
rm -rf .* * || : | |
cp -rp $TEMP_DIR/. . | |
rm -rf $TEMP_DIR | |
ls | |
- name: Get charm name | |
id: get-charm-name | |
run: | | |
set -x | |
CHARM_NAME="$([ -f metadata.yaml ] && yq '.name' metadata.yaml || echo UNKNOWN)" | |
if [ "$CHARM_NAME" == "UNKNOWN" ]; then | |
CHARM_NAME="$([ -f charmcraft.yaml ] && yq '.name' charmcraft.yaml || echo UNKNOWN)" | |
fi | |
echo "CHARM_NAME=$CHARM_NAME">> $GITHUB_ENV | |
- name: Download charm artifact | |
# TODO if: ${{ github.event_name == 'push' }} | |
if: true | |
run: | | |
gh run download ${{ needs.get-run-id.outputs.run-id }} -R ${{ github.repository }} -n ${{ env.CHARM_NAME }}-charm | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Download charm artifact (for testing) | |
uses: actions/download-artifact@v4 | |
# TODO if: ${{ github.event_name == 'pull_request' }} | |
if: false | |
with: | |
name: ${{ env.CHARM_NAME }}-charm | |
path: ${{ env.working_directory }} | |
- name: Get charm file | |
id: get-charm-file | |
run: | | |
echo "CHARM_FILE=$(ls ${{ env.CHARM_NAME }}_*.charm)" >> $GITHUB_OUTPUT | |
- name: Upload charm to charmhub | |
env: | |
CHARMCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "true" | |
CHARMCRAFT_AUTH: ${{ secrets.CHARMHUB_TOKEN }} | |
CHARM_FILE: ${{ steps.get-charm-file.outputs.CHARM_FILE }} | |
run: | | |
charmcraft resource-revisions netbox django-app-image | |
# it looks like this is not necessary, but it is what the canonical/charming-actions/upload-charm does. | |
MAX_REV=$(charmcraft resource-revisions netbox django-app-image --format=json | jq 'map( .revision) | max') | |
echo max_rev ${MAX_REV} | |
charmcraft upload --format json --release ${channel} ${CHARM_FILE} --resource=django-app-image:${MAX_REV} |