forked from Automattic/jetpack
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
build: Move "Test plugin upgrades" to a post-build workflow
GitHub has an unfortunate behavior in that workflow artifacts are not available via the API until the entire workflow has completed. This means that the "Test plugin upgrades" job in the build workflow unnecessarily delays the availability of the build artifact for Jetpack Live Branches and future wpcom automated testing for 6 or so minutes. To get around this, we create a new "Post-Build" workflow that is triggered by `workflow_run` after the Build workflow completes. But since this new workflow isn't automatically attached to the PR, we have to make API calls to get it to show up there. This is a second attempt at Automattic#25892, which had to be reverted as using the Actions app put the checks into the "suite" of a random workflow.
- Loading branch information
Showing
4 changed files
with
307 additions
and
50 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
name: "Check Run" | ||
description: "Create or update a check run. This is a simple wrapper around GitHub's checks API, https://docs.github.com/en/rest/checks/runs." | ||
inputs: | ||
id: | ||
description: "Check run ID to update. If not given, a new run will be created" | ||
sha: | ||
description: "The SHA of the commit." | ||
name: | ||
description: "The name of the check. For example, \"code-coverage\"." | ||
status: | ||
description: "The current status. Can be one of: `queued`, `in_progress`, `completed`" | ||
conclusion: | ||
description: "The final conclusion of the check. Can be one of: `action_required`, `cancelled`, `failure`, `neutral`, `success`, `skipped`, `timed_out`" | ||
title: | ||
description: "Title of the check. Shown in the PR's checks list." | ||
summary: | ||
description: "Summary of the check. Can contain Markdown." | ||
token: | ||
description: "App access token. See https://docs.github.com/en/developers/apps/building-github-apps/authenticating-with-github-apps#authenticating-as-a-github-app for how to get one." | ||
outputs: | ||
id: | ||
description: "Check run ID." | ||
value: ${{ steps.run.outputs.id }} | ||
runs: | ||
using: composite | ||
steps: | ||
- id: run | ||
shell: bash | ||
env: | ||
ID: ${{ inputs.id }} | ||
SHA: ${{ inputs.sha }} | ||
NAME: ${{ inputs.name }} | ||
STATUS: ${{ inputs.status }} | ||
CONCLUSION: ${{ inputs.conclusion }} | ||
TITLE: ${{ inputs.title }} | ||
SUMMARY: ${{ inputs.summary }} | ||
TOKEN: ${{ inputs.token }} | ||
run: | | ||
if [[ -n "$ID" ]]; then | ||
METHOD=PATCH | ||
URL="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/check-runs/$ID" | ||
else | ||
METHOD=POST | ||
URL="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/check-runs" | ||
fi | ||
DATA="{}" | ||
if [[ -n "$NAME" ]]; then | ||
DATA="$(jq --arg v "$NAME" '.name |= $v' <<<"$DATA")" | ||
fi | ||
if [[ -n "$SHA" ]]; then | ||
DATA="$(jq --arg v "$SHA" '.head_sha |= $v' <<<"$DATA")" | ||
fi | ||
if [[ -n "$STATUS" ]]; then | ||
DATA="$(jq --arg v "$STATUS" '.status |= $v' <<<"$DATA")" | ||
fi | ||
if [[ -n "$CONCLUSION" ]]; then | ||
DATA="$(jq --arg v "$CONCLUSION" '.conclusion |= $v' <<<"$DATA")" | ||
fi | ||
if [[ -n "$TITLE" ]]; then | ||
DATA="$(jq --arg v "$TITLE" '.output.title |= $v' <<<"$DATA")" | ||
fi | ||
if [[ -n "$SUMMARY" ]]; then | ||
DATA="$(jq --arg v "$SUMMARY" '.output.summary |= $v' <<<"$DATA")" | ||
fi | ||
echo "Data: $DATA" | ||
JSON="$(curl -v -X "$METHOD" --header "authorization: Bearer $TOKEN" --url "$URL" --data "$DATA")" | ||
echo "$JSON" | ||
echo "id=$(jq -r .id <<<"$JSON")" >> "$GITHUB_OUTPUT" |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
name: Post-Build | ||
on: | ||
workflow_run: | ||
types: [ 'completed' ] | ||
workflows: | ||
- Build | ||
concurrency: | ||
# Cancel concurrent jobs on pull_request but not push, by including the run_id in the concurrency group for the latter. | ||
group: post-build-${{ github.event.workflow_run.event == 'push' && github.run_id || 'pr' }}-${{ github.event.workflow_run.head_branch }} | ||
cancel-in-progress: true | ||
|
||
env: | ||
COMPOSER_ROOT_VERSION: "dev-trunk" | ||
SUMMARY: Post-Build run [#${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for Build run [#${{ github.event.workflow_run.id }}](${{ github.event.workflow_run.html_url }}) | ||
|
||
# Note the job logic here is a bit unusual. That's because this workflow is triggered by `workflow_run`, and so is not shown on the PR by default. | ||
# Instead we have to manually report back, including where we could normally just skip or let a failure be handled. | ||
# - If the "Build" job failed, we need to set our status as failed too (build_failed). | ||
# - If the find_artifact job fails for some reason, we need a step to explicitly report that back. | ||
# - If no plugins are found, we need to explicitly report back a "skipped" status. | ||
# - And the upgrade_test job both explicitly sets "in progress" at its start and updates at its end. | ||
|
||
jobs: | ||
setup: | ||
name: Setup | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 2 # 2022-12-20: Seems like it should be fast. | ||
outputs: | ||
token: ${{ steps.get_token.outputs.token }} | ||
upgrade_check: ${{ steps.upgrade_check.outputs.id }} | ||
steps: | ||
- name: Get token | ||
id: get_token | ||
uses: getsentry/action-github-app-token@v2.0.0 | ||
with: | ||
app_id: ${{ secrets.JP_LAUNCH_CONTROL_ID }} | ||
private_key: ${{ secrets.JP_LAUNCH_CONTROL_KEY }} | ||
|
||
- uses: actions/checkout@v3 | ||
|
||
- name: 'Create "Test plugin upgrades" check' | ||
id: upgrade_check | ||
uses: ./.github/actions/check-run | ||
with: | ||
name: Test plugin upgrades | ||
sha: ${{ github.event.workflow_run.head_sha }} | ||
status: queued | ||
summary: | | ||
${{ env.SUMMARY }} | ||
token: ${{ steps.get_token.outputs.token }} | ||
|
||
build_failed: | ||
name: Handle build failure | ||
runs-on: ubuntu-latest | ||
needs: setup | ||
if: github.event.workflow_run.conclusion != 'success' | ||
timeout-minutes: 2 # 2022-08-26: Seems like it should be fast. | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: 'Mark "Test plugin upgrades" cancelled' | ||
uses: ./.github/actions/check-run | ||
with: | ||
id: ${{ needs.setup.outputs.upgrade_check }} | ||
conclusion: cancelled | ||
title: Build failed | ||
summary: | | ||
${{ env.SUMMARY }} | ||
Post-build run aborted because the build did not succeed. | ||
token: ${{ needs.setup.outputs.token }} | ||
|
||
find_artifact: | ||
name: Find artifact | ||
runs-on: ubuntu-latest | ||
needs: setup | ||
if: github.event.workflow_run.conclusion == 'success' | ||
timeout-minutes: 2 # 2022-08-26: Seems like it should be fast. | ||
outputs: | ||
zip_url: ${{ steps.run.outputs.zip_url }} | ||
any_plugins: ${{ steps.run.outputs.any_plugins }} | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Find artifact | ||
id: run | ||
env: | ||
TOKEN: ${{ github.token }} | ||
URL: ${{ github.event.workflow_run.artifacts_url }} | ||
run: | | ||
for (( i=1; i<=5; i++ )); do | ||
[[ $i -gt 1 ]] && sleep 10 | ||
echo "::group::Fetch list of artifacts (attempt $i/5)" | ||
JSON="$(curl -v -L --get \ | ||
--header "Authorization: token $TOKEN" \ | ||
--url "$URL" | ||
)" | ||
echo "$JSON" | ||
echo "::endgroup::" | ||
ZIPURL="$(jq -r '.artifacts[] | select( .name == "jetpack-build" ) | .archive_download_url' <<<"$JSON")" | ||
PLUGINS="$(jq -r '.artifacts[] | select( .name == "plugins" )' <<<"$JSON")" | ||
if [[ -n "$ZIPURL" ]]; then | ||
break | ||
fi | ||
done | ||
[[ -z "$ZIPURL" ]] && { echo "::error::Failed to find artifact."; exit 1; } | ||
echo "Zip URL: $ZIPURL" | ||
echo "::set-output name=zip_url::${ZIPURL}" | ||
if [[ -z "$PLUGINS" ]]; then | ||
echo "Any plugins? No" | ||
echo "::set-output name=any_plugins::false" | ||
else | ||
echo "Any plugins? Yes" | ||
echo "::set-output name=any_plugins::true" | ||
fi | ||
- name: 'Mark "Test plugin upgrades" failed' | ||
if: ${{ ! success() }} | ||
uses: ./.github/actions/check-run | ||
with: | ||
id: ${{ needs.setup.outputs.upgrade_check }} | ||
conclusion: failure | ||
title: Failed to find build artifact | ||
summary: | | ||
${{ env.SUMMARY }} | ||
Post-build run aborted because the "Find artifact" step failed. | ||
token: ${{ needs.setup.outputs.token }} | ||
|
||
no_plugins: | ||
name: Handle no-plugins | ||
runs-on: ubuntu-latest | ||
needs: [ setup, find_artifact ] | ||
if: needs.find_artifact.outputs.any_plugins == 'false' | ||
timeout-minutes: 2 # 2022-08-26: Seems like it should be fast. | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: 'Mark "Test plugin upgrades" skipped' | ||
uses: ./.github/actions/check-run | ||
with: | ||
id: ${{ needs.setup.outputs.upgrade_check }} | ||
conclusion: skipped | ||
title: No plugins were built | ||
summary: | | ||
${{ env.SUMMARY }} | ||
Post-build run skipped because no plugins were built. | ||
token: ${{ needs.setup.outputs.token }} | ||
|
||
upgrade_test: | ||
name: Test plugin upgrades | ||
runs-on: ubuntu-latest | ||
needs: [ setup, find_artifact ] | ||
if: needs.find_artifact.outputs.any_plugins == 'true' | ||
timeout-minutes: 15 # 2022-08-26: Successful runs seem to take about 6 minutes, but give some extra time for the downloads. | ||
services: | ||
db: | ||
image: mariadb:latest | ||
env: | ||
MARIADB_ROOT_PASSWORD: wordpress | ||
ports: | ||
- 3306:3306 | ||
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5 | ||
container: | ||
image: ghcr.io/automattic/jetpack-wordpress-dev:latest | ||
env: | ||
WP_DOMAIN: localhost | ||
WP_ADMIN_USER: wordpress | ||
WP_ADMIN_EMAIL: wordpress@example.com | ||
WP_ADMIN_PASSWORD: wordpress | ||
WP_TITLE: Hello World | ||
MYSQL_HOST: db:3306 | ||
MYSQL_DATABASE: wordpress | ||
MYSQL_USER: root | ||
MYSQL_PASSWORD: wordpress | ||
HOST_PORT: 80 | ||
ports: | ||
- 80:80 | ||
steps: | ||
- uses: actions/checkout@v3 | ||
with: | ||
path: monorepo | ||
|
||
- name: Notify check in progress | ||
uses: ./monorepo/.github/actions/check-run | ||
with: | ||
id: ${{ needs.setup.outputs.upgrade_check }} | ||
status: in_progress | ||
title: Test started... | ||
summary: | | ||
${{ env.SUMMARY }} | ||
See run [#${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. | ||
token: ${{ needs.setup.outputs.token }} | ||
|
||
- name: Download build artifact | ||
env: | ||
TOKEN: ${{ github.token }} | ||
ZIPURL: ${{ needs.find_artifact.outputs.zip_url }} | ||
shell: bash | ||
run: | | ||
for (( i=1; i<=2; i++ )); do | ||
[[ $i -gt 1 ]] && sleep 10 | ||
echo "::group::Downloading artifact (attempt $i/2)" | ||
curl -v -L --get \ | ||
--header "Authorization: token $TOKEN" \ | ||
--url "$ZIPURL" \ | ||
--output "artifact.zip" | ||
echo "::endgroup::" | ||
if [[ -e "artifact.zip" ]] && zipinfo artifact.zip &>/dev/null; then | ||
break | ||
fi | ||
done | ||
[[ ! -e "artifact.zip" ]] && { echo "::error::Failed to download artifact."; exit 1; } | ||
unzip artifact.zip | ||
tar --xz -xvvf build.tar.xz | ||
- name: Setup WordPress | ||
run: monorepo/.github/files/test-plugin-update/setup.sh | ||
|
||
- name: Prepare plugin zips | ||
run: monorepo/.github/files/test-plugin-update/prepare-zips.sh | ||
|
||
- name: Test upgrades | ||
run: monorepo/.github/files/test-plugin-update/test.sh | ||
|
||
- name: Notify final status | ||
if: always() | ||
uses: ./monorepo/.github/actions/check-run | ||
with: | ||
id: ${{ needs.setup.outputs.upgrade_check }} | ||
conclusion: ${{ job.status }} | ||
title: ${{ job.status == 'success' && 'Tests passed' || job.status == 'cancelled' && 'Cancelled' || 'Tests failed' }} | ||
summary: | | ||
${{ env.SUMMARY }} | ||
See run [#${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. | ||
token: ${{ needs.setup.outputs.token }} |
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