Skip to content

Release app

Release app #149

Workflow file for this run

name: Release app
on:
workflow_dispatch:
inputs:
app:
type: choice
options:
- api
- ingestion_server
- frontend
- catalog
required: true
description: Application to release. If `api` or `frontend`, the deployment workflow will automatically be dispatched for you.
image-sha:
type: string
required: true
description: The SHA of the staging image to tag.
concurrency: ${{ github.workflow }}-${{ inputs.app }}
jobs:
release-app:
name: Release app
runs-on: ubuntu-latest
permissions:
# Needed to create the GitHub release on the repo
contents: write
# Needed for pushing the new docker image tag
packages: write
# Needed to open the changelog PR
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
# Creating the tag requires having the whole history of `main`
fetch-depth: 0
- name: Validate `sha-tag` input
uses: actions/github-script@v6
with:
script: |
let exists = undefined,
page = 0
while (!exists) {
page += 1
const { data: versions } =
await github.rest.packages.getAllPackageVersionsForPackageOwnedByOrg({
package_type: 'container',
// We do not have to validate that auxiliary images also exist as they're built at the same time
// as the "main" image. e.g., `api_nginx` is always built when `api` is built and they'll have
// the same set of tags.
package_name: 'openverse-${{ inputs.app }}',
org: 'WordPress',
page,
// max of `per_page`
per_page: 100,
})
if (!versions.length) {
break
}
exists = versions.some((v) => v.metadata.container.tags.includes('${{ inputs.image-sha }}'))
}
if (!exists) {
throw new Error(
`'${{ inputs.image-sha }}' does not appear to be a valid SHA tag for ${{ inputs.app }}.`
)
}
- name: Calculate tag name
id: tag
run: |
# Format example: 2023.03.22.04.56.29
# `-u` forces UTC
formatted_date="$(date -u +%Y.%m.%d.%H.%M.%S)"
# Split image and git tag to avoid app name duplicated in the fully qualified image name
{
echo "date=$formatted_date";
echo "git-tag=${{ inputs.app }}-$formatted_date";
echo "image-tag=rel-$formatted_date";
} >> "$GITHUB_OUTPUT"
- name: Log in to GitHub Docker Registry
uses: docker/login-action@v3
with:
registry: https://ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Add new tag to existing docker image
run: |
docker buildx imagetools create ghcr.io/wordpress/openverse-${{ inputs.app }}:${{ inputs.image-sha }} --tag ghcr.io/wordpress/openverse-${{ inputs.app }}:${{ steps.tag.outputs.image-tag }}
if [[ "${{ inputs.app }}" == "api" ]] || [[ "${{ inputs.app }}" == "frontend" ]]; then
docker buildx imagetools create ghcr.io/wordpress/openverse-${{ inputs.app }}_nginx:${{ inputs.image-sha }} --tag ghcr.io/wordpress/openverse-${{ inputs.app }}_nginx:${{ steps.tag.outputs.image-tag }}
fi
- name: Deploy production application
if: inputs.app == 'frontend' || inputs.app == 'api'
uses: felixp8/[email protected]
with:
owner: WordPress
repo: openverse-infrastructure
token: ${{ secrets.ACCESS_TOKEN }}
event_type: deploy_production_${{ inputs.app == 'frontend' && 'nuxt' || inputs.app }}
client_payload: |
{
"actor": "${{ github.actor }}",
"tag": "${{ steps.tag.outputs.image-tag }}"
}
wait_time: 60 # check every minute
max_time: 1800 # allow up to 30 minutes for a deployment
# max_time can't easily be configured per application
# without duplicating information between our infrastructure
# and this workflow. The upstream workflows already have
# timeouts appropriately configured and will all fail before 30
# minutes is reached. On the other hand, we do want to wait
# so that there is a record of the successful deployment.
- name: Create and publish release
uses: release-drafter/release-drafter@v5
id: release-drafter
with:
config-name: release-drafter-${{ inputs.app }}.yml
version: ${{ steps.tag.outputs.date }}
tag: ${{ steps.tag.outputs.git-tag }}
name: ${{ steps.tag.outputs.git-tag }}
publish: true
commitish: main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Add new changelog file to documentation
env:
APP: ${{ inputs.app }}
DATE: ${{ steps.tag.outputs.date }}
RELEASE_BODY: ${{ steps.release-drafter.outputs.body }}
working-directory: automations/python/workflows
run: python write_changelog.py
- name: Setup CI env
uses: ./.github/actions/setup-env
with:
# Python is not needed to run pre-commit.
setup_python: false
# Node.js is needed by lint actions.
install_recipe: "node-install"
- name: Cache pre-commit envs
uses: actions/cache@v3
with:
path: ~/.cache/pre-commit
key: ${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Lint the changelog file so that it passes CI
run: |
# Add the new changelog file to git so that pre-commit can lint it.
git add documentation/changelogs/${{ inputs.app }}/${{ steps.tag.outputs.date }}.md
just precommit
# Ensure this step passes even if linting has made changes so the workflow can continue
just lint || true
- name: Open changelog PR
uses: peter-evans/create-pull-request@v5
if: ${{ !cancelled() }}
with:
# Access token necessary for PRs to run with CI
token: ${{ secrets.ACCESS_TOKEN }}
base: main
branch: changelog/${{ steps.tag.outputs.git-tag }}
commit-message: Publish changelog for ${{ steps.tag.outputs.git-tag }}
title: Publish changelog for ${{ steps.tag.outputs.git-tag }}
# Add labels to pass CI
labels: |
🧱 stack: ${{ inputs.app == 'ingestion_server' && 'ingestion server' || inputs.app }}
🌟 goal: addition
📄 aspect: text
🟩 priority: low
skip-changelog
body: |
This changelog PR was automatically generated for @${{ github.actor }} as a result of the ${{ github.workflow }} workflow.