Skip to content

Commit

Permalink
Separate release drafting from publishing (#3755)
Browse files Browse the repository at this point in the history
* WIP Separate release drafting from publishing

* Remove testing code

* Resolve confusion of where the release is drafted

* Update documentation for new release process
  • Loading branch information
sarayourfriend authored Feb 12, 2024
1 parent 30abcc4 commit 33b421f
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 125 deletions.
57 changes: 57 additions & 0 deletions .github/workflows/draft_releases.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Draft releases

on:
push:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
# Freely interrupt release drafting workflows, they do not depend on each other and always generate the full release based on the previous one
cancel-in-progress: true

jobs:
draft-release:
name: "Draft ${{ matrix.app }} release"
runs-on: ubuntu-latest
permissions:
# write permission is required to create a github release
contents: write

strategy:
matrix:
app:
- api
- frontend
- catalog
- ingestion_server

steps:
- uses: actions/checkout@v4

- 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)"
{
echo "date=$formatted_date";
echo "git-tag=${{ env.APP_NAME }}-$formatted_date";
} >> "$GITHUB_OUTPUT"
# Each time this runs, it should replace the previous drafted release matching the tag prefix set in the release drafter config
# This means there will always be a running drafted release for all apps
# Publishing the drafted release triggers the `release-app` workflow
- uses: release-drafter/release-drafter@v5
id: release-drafter
with:
config-name: release-drafter-${{ matrix.app }}.yml
version: ${{ steps.tag.outputs.date }}
tag: ${{ matrix.app }}-${{ steps.tag.outputs.git-tag }}
name: ${{ matrix.app }}-${{ steps.tag.outputs.git-tag }}
draft: true
commitish: main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
115 changes: 36 additions & 79 deletions .github/workflows/release-app.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
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 }}
release:
types: [released]

# The app-name expression is duplicated between here and `env` below because neither context is able to reference the other
# but both need it
concurrency: >
${{ github.workflow }}-
${{
startsWith(github.ref_name, 'api-') && 'api'
|| startsWith(github.ref_name, 'ingestion_server-') && 'ingestion_server'
|| startsWith(github.ref_name, 'catalog-') && 'catalog'
|| startsWith(github.ref_name, 'frontend-') && 'frontend'
}}
jobs:
release-app:
Expand All @@ -32,55 +28,29 @@ jobs:
packages: write
# Needed to open the changelog PR
pull-requests: write
env:
APP_NAME: >
${{
startsWith(github.ref_name, 'api-') && 'api'
|| startsWith(github.ref_name, 'ingestion_server-') && 'ingestion_server'
|| startsWith(github.ref_name, 'catalog-') && 'catalog'
|| startsWith(github.ref_name, 'frontend-') && 'frontend'
}}
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)"
release_date=$(echo '${{ github.ref_name }}' | sed 's/${{ env.APP_NAME }}//')
# Split image and git tag to avoid app name duplicated in the fully qualified image name
# Generate `rel-` prefixed image tag to avoid duplicated app name between image and tag
{
echo "date=$formatted_date";
echo "git-tag=${{ inputs.app }}-$formatted_date";
echo "image-tag=rel-$formatted_date";
echo "date=$release_date";
echo "image-tag=rel-$release_date";
} >> "$GITHUB_OUTPUT"
- name: Log in to GitHub Docker Registry
Expand All @@ -90,22 +60,22 @@ jobs:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Add new tag to existing docker image
- name: Tag latest with release tag
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 }}
docker buildx imagetools create ghcr.io/wordpress/openverse-${{ env.APP_NAME }}:latest --tag ghcr.io/wordpress/openverse-${{ env.APP_NAME }}:${{ 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 }}
if [[ "${{ env.APP_NAME }}" == "api" ]] || [[ "${{ env.APP_NAME }}" == "frontend" ]]; then
docker buildx imagetools create ghcr.io/wordpress/openverse-${{ env.APP_NAME }}_nginx:latest --tag ghcr.io/wordpress/openverse-${{ env.APP_NAME }}_nginx:${{ steps.tag.outputs.image-tag }}
fi
- name: Deploy production application
if: inputs.app == 'frontend' || inputs.app == 'api'
if: env.APP_NAME == 'frontend' || env.APP_NAME == '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 }}
event_type: deploy_production_${{ env.APP_NAME == 'frontend' && 'nuxt' || env.APP_NAME }}
client_payload: |
{
"actor": "${{ github.actor }}",
Expand All @@ -120,24 +90,11 @@ jobs:
# 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 }}
APP: ${{ env.APP_NAME }}
DATE: ${{ steps.tag.outputs.date }}
RELEASE_BODY: ${{ steps.release-drafter.outputs.body }}
RELEASE_BODY: ${{ github.event.release.body }}
working-directory: automations/python/workflows
run: python write_changelog.py

Expand All @@ -158,14 +115,14 @@ jobs:
- 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
git add documentation/changelogs/${{ env.APP_NAME }}/${{ 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() }}
if: "!cancelled()"
with:
# Access token necessary for PRs to run with CI
token: ${{ secrets.ACCESS_TOKEN }}
Expand All @@ -175,7 +132,7 @@ jobs:
title: Publish changelog for ${{ steps.tag.outputs.git-tag }}
# Add labels to pass CI
labels: |
🧱 stack: ${{ inputs.app == 'ingestion_server' && 'ingestion server' || inputs.app }}
🧱 stack: ${{ env.APP_NAME == 'ingestion_server' && 'ingestion server' || env.APP_NAME }}
🌟 goal: addition
📄 aspect: text
🟩 priority: low
Expand Down
15 changes: 4 additions & 11 deletions documentation/api/guides/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,10 @@
For more information on how deployments work, please see the [general deployment guide](/general/deployment.md).
```

1. Visit
[https://api-staging.openverse.engineering/version](https://api-staging.openverse.engineering/version)
and
[the API Docker image](https://github.com/wordpress/openverse/pkgs/container/openverse-api).
Verify that the commit SHA live on the staging site is also tagged with
`latest` in the Docker image.
![GitHub package directory screenshot](/_static/package_directory_example.png)
1. Release the app via
[GitHub workflow](https://github.com/WordPress/openverse/actions/workflows/release-app.yml).
Click the "Run workflow" button, choose "api" from the dropdown, and supply
the SHA identified in step 1.
1. [Publish the drafted API release in the GitHub release page of the monorepo](https://github.com/WordPress/openverse/releases?q=api-)
- Here you can preview the changes included in the API release and decide
whether a release is necessary and adjust monitoring during the deployment
accordingly.
1. That's it! The API will be deployed. You can monitor the deployment in the
maintainers `#openverse-notifications` channel and in the
[infrastructure repository's workflow listing](https://github.com/WordPress/openverse-infrastructure/actions).
Expand Down
11 changes: 4 additions & 7 deletions documentation/catalog/guides/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@
unpause it back.
```

1. Visit the
[Catalog Docker image](https://github.com/WordPress/openverse/pkgs/container/openverse-catalog)
page and copy the SHA of the image tagged `latest`.
1. Release the app via
[GitHub workflow](https://github.com/WordPress/openverse/actions/workflows/release-app.yml).
Click the "Run workflow" button, choose "catalog" from the dropdown, and
supply the SHA identified in the previous step
1. [Publish the drafted catalog release in the GitHub release page of the monorepo](https://github.com/WordPress/openverse/releases?q=catalog-)
- Here you can preview the changes included in the catalog release and decide
whether a release is necessary and adjust monitoring during the deployment
accordingly.

## Deployment

Expand Down
15 changes: 4 additions & 11 deletions documentation/frontend/guides/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,10 @@
For more information on how deployments work, please see the [general deployment guide](/general/deployment.md).
```

1. Visit
[https://staging.openverse.org/version.json](https://staging.openverse.org/version.json)
and
[the frontend Docker image](https://github.com/wordpress/openverse/pkgs/container/openverse-frontend).
Verify that the commit SHA live on the staging site is also tagged with
`latest` in the Docker image.
![GitHub package directory screenshot](/_static/package_directory_example.png)
1. Release the app via
[GitHub workflow](https://github.com/WordPress/openverse/actions/workflows/release-app.yml).
Click the "Run workflow" button, choose "frontend" from the dropdown, and
supply the SHA identified in step 1.
1. [Publish the drafted frontend release in the GitHub release page of the monorepo](https://github.com/WordPress/openverse/releases?q=frontend-)
- Here you can preview the changes included in the frontend release and
decide whether a release is necessary and adjust monitoring during the
deployment accordingly.
1. That's it. The frontend will be deployed. You can monitor the deployment in
the maintainers `#openverse-notifications` channel and in the
[infrastructure repository's workflow listing](https://github.com/WordPress/openverse-infrastructure/actions).
Expand Down
17 changes: 7 additions & 10 deletions documentation/general/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,21 +143,18 @@ the process above. The staging deployment workflows

## Production

Maintainers manually dispatch the production deployment via the
[Release app](https://github.com/WordPress/openverse/actions/workflows/release-app.yml)
workflow. The workflow requires the tag of an existing Docker image to tag as
the "released" image. It generates a date-based tag for the specific application
being released, publishes a GitHub Release (which creates a git tag), tags the
Docker image, and then triggers the deployment workflow. The workflow also opens
a PR to add the changelog to the
Maintainers begin the production deployment process by publishing the drafted
release for an application. Publishing a release automatically tags the latest
docker image for the application and opens a PR to add the changelog to the
[documentation site's changelog directory](https://docs.openverse.org/changelogs/index.html).
This needs to be manually approved and merged by maintainers. The person who
triggers the release app workflow is pinged in the PR description to help with
the visibility of the PR.

The same workflow is used to create production release images for the ingestion
server. In that case the production deployment still needs to be handled via
Terraform.
For the API and frontend, publishing the release also triggers an automated
production deployment. For the catalog and ingestion server, however,
maintainers must manually deploy the changes to production using the Terraform
deployment process.

## Rollbacks

Expand Down
11 changes: 4 additions & 7 deletions documentation/ingestion_server/guides/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@

1. Check [Airflow](https://airflow.openverse.engineering/home?tags=data_refresh)
to make sure a data refresh isn't occurring.
1. Visit the
[Ingestion Server Docker image](https://github.com/WordPress/openverse/pkgs/container/openverse-ingestion_server)
page and copy the SHA of the image tagged `latest`.
1. Release the app via
[GitHub workflow](https://github.com/WordPress/openverse/actions/workflows/release-app.yml).
Click the "Run workflow" button, choose "ingestion_server" from the dropdown,
and supply the SHA identified in the previous step.
1. [Publish the drafted ingestion server release in the GitHub release page of the monorepo](https://github.com/WordPress/openverse/releases?q=ingestion_server-)
- Here you can preview the changes included in the ingestion server release
and decide whether a release is necessary and adjust monitoring during the
deployment accordingly.

## Deployment

Expand Down

0 comments on commit 33b421f

Please sign in to comment.