Release app #149
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
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. |