Skip to content

Commit

Permalink
Publish subsequent internal releases right after building (#2306)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/0/1206676349038948/f

Description:
This change combines Bump Internal Release and Publish DMG Release workflows in that the former
calls the latter. As a result, bumping internal release is a single workflow run.
  • Loading branch information
ayoy authored Mar 4, 2024
1 parent 039e434 commit 676528e
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ data:
<body>
<h2>Internal release build ${TAG} ready ✅</h2>
<ul>
<li>📥 DMG is available from <a href='${DMG_URL}'>${DMG_URL}</a>.</li>
<li>📥 DMG is available from <a href='${DMG_URL}'>${DMG_URL}</a>.
<ul>
<li>If this is a subsequent internal release (started by calling <em>Bump Internal Release</em> workflow), the DMG will be automatically published to Sparkle in a few minutes. Sit tight.</li>
</ul></li>
<li>🏷️ Repository is tagged with <code>${TAG}</code> tag.</li>
<li>🚢 GitHub <a href='${RELEASE_URL}'>${TAG} pre-release</a> is created.</li>
<li>🔱 <code>${BRANCH}</code> branch has been successfully merged to <code>${BASE_BRANCH}</code>.</li>
Expand Down
4 changes: 4 additions & 0 deletions .github/actions/asana-create-action-item/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ runs:
shell: bash
env:
ASSIGNEE_ID: ${{ steps.get-automation-subtask.outputs.assignee-id }}
AUTOMATION_TASK_ID: ${{ steps.get-automation-subtask.outputs.automation-task-id }}
TEMPLATE_PATH: ${{ github.action_path }}/templates/${{ inputs.template-name }}.yml
WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
if [ ! -f $TEMPLATE_PATH ]; then
echo "::error::Template file not found at $TEMPLATE_PATH"
Expand All @@ -64,6 +66,7 @@ runs:
shell: bash
env:
ASSIGNEE_ID: ${{ steps.get-automation-subtask.outputs.assignee-id }}
AUTOMATION_TASK_ID: ${{ steps.get-automation-subtask.outputs.automation-task-id }}
NOTES: ${{ inputs.notes }}
TASK_NAME: ${{ inputs.task-name }}
WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
Expand All @@ -76,6 +79,7 @@ runs:
shell: bash
env:
ASSIGNEE_ID: ${{ steps.get-automation-subtask.outputs.assignee-id }}
AUTOMATION_TASK_ID: ${{ steps.get-automation-subtask.outputs.automation-task-id }}
HTML_NOTES: ${{ inputs.html-notes }}
TASK_NAME: ${{ inputs.task-name }}
WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
data:
name: Run Publish DMG Release GitHub Actions workflow
assignee: "${ASSIGNEE_ID}"
html_notes: |
<body>
<h1>Using GH CLI</h1>
Run the following command:
<code>gh workflow run publish_dmg_release.yml --ref ${BRANCH} -f asana-task-url=${ASANA_TASK_URL} -f tag=${TAG} -f release-type=internal</code>
<h1>Using GitHub web UI</h1>
<ol>
<li>Open <a href='https://github.com/duckduckgo/macos-browser/actions/workflows/publish_dmg_release.yml'>Publish DMG Release workflow page</a>.</li>
<li>Click "Run Workflow" and fill in the form as follows:
<ul>
<li><b>Branch</b> <code>${BRANCH}</code></li>
<li><b>Asana release task URL</b> <code>${ASANA_TASK_URL}</code></li>
<li><b>Tag to publish</b> <code>${TAG}</code></li>
<li><b>Release Type</b> <code>internal</code></li>
</ul></li>
</ol>
The GitHub Action workflow does the following:
<ul>
<li>Fetches the release DMG from staticcdn.duckduckgo.com</li>
<li>Extracts release notes from the Asana task description</li>
<li>Runs <code>appcastManager</code> to generate the new appcast2.xml file</li>
<li>Stores the diff against previous version and the copy of the old appcast2.xml file</li>
<li>Uploads new appcast, DMG and binary delta files to S3</li>
<li>On success, creates a task for the release DRI to validate that "Check for Updates" works, with instructions on how to revert that change if "Check for Updates" is broken.</li>
<li>On failure, creates a task for the release DRI with manual instructions on generating the appcast and uploading to S3.</li>
</ul>
Complete this task when ready and proceed with testing the build. If GitHub Actions is unavailable, you'll find manual instructions in the <em>Run Publish DMG Release GitHub Actions workflow</em> subtask of <em>Make Internal Release</em> task.
🔗 Workflow URL: <a href='${WORKFLOW_URL}'>${WORKFLOW_URL}</a>.
</body>
3 changes: 2 additions & 1 deletion .github/actions/asana-log-message/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ inputs:
type: string
template-name:
description: |
Name of a template file (without extension) for the comment, relative to 'templates' subdirectory of the action.
Name of a template file (without extension) for the comment, relative to 'templates'
subdirectory of the 'asana-add-comment' action.
The file is processed by envsubst before being sent to Asana.
required: false
type: string
Expand Down

This file was deleted.

8 changes: 0 additions & 8 deletions .github/actions/asana-log-message/templates/dmg-uploaded.yml

This file was deleted.

This file was deleted.

This file was deleted.

14 changes: 14 additions & 0 deletions .github/workflows/bump_internal_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ jobs:
branch: ${{ github.ref_name }}
base-branch: ${{ github.event.inputs.base-branch || 'main' }}
prerelease: true
internal-release-bump: true
secrets:
ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
GHA_ELEVATED_PERMISSIONS_TOKEN: ${{ secrets.GHA_ELEVATED_PERMISSIONS_TOKEN }}

publish_release:
name: Publish DMG Release
needs: [ tag_and_merge ]
uses: ./.github/workflows/publish_dmg_release.yml
with:
asana-task-url: ${{ github.event.inputs.asana-task-url }}
secrets:
ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
AWS_ACCESS_KEY_ID_RELEASE_S3: ${{ secrets.AWS_ACCESS_KEY_ID_RELEASE_S3 }}
AWS_SECRET_ACCESS_KEY_RELEASE_S3: ${{ secrets.AWS_SECRET_ACCESS_KEY_RELEASE_S3 }}
GHA_ELEVATED_PERMISSIONS_TOKEN: ${{ secrets.GHA_ELEVATED_PERMISSIONS_TOKEN }}
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
68 changes: 48 additions & 20 deletions .github/workflows/publish_dmg_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,34 @@ on:
- internal
- public
- hotfix
workflow_call:
inputs:
asana-task-url:
description: "Asana release task URL"
required: true
type: string
secrets:
ASANA_ACCESS_TOKEN:
required: true
AWS_ACCESS_KEY_ID_RELEASE_S3:
required: true
AWS_SECRET_ACCESS_KEY_RELEASE_S3:
required: true
GHA_ELEVATED_PERMISSIONS_TOKEN:
required: true
SPARKLE_PRIVATE_KEY:
required: true

jobs:

# This is only run for public and hotfix releases
# This is only run for public and hotfix releases, so only when it's triggered manually.
# Internal release has been tagged as part of code_freeze or bump_interal_release workflows
tag-public-release:

name: Tag public release

if: ${{ github.event.inputs.release-type != 'internal' }}
# Run if release-type is provided (not empty) an is not internal
if: contains(github.event.inputs.release-type, '') == false && github.event.inputs.release-type != 'internal'

uses: ./.github/workflows/tag_release.yml
with:
Expand All @@ -43,6 +61,10 @@ jobs:

name: Publish a release to Sparkle

env:
RELEASE_TYPE: ${{ github.event.inputs.release-type || 'internal' }}
SPARKLE_DIR: ${{ github.workspace }}/sparkle-updates

needs: [tag-public-release]

# Allow to run even if the tag-public-release job was skipped (e.g. for internal releases)
Expand All @@ -52,23 +74,34 @@ jobs:
runs-on: macos-13-xlarge
timeout-minutes: 10

env:
SPARKLE_DIR: ${{ github.workspace }}/sparkle-updates

steps:

- name: Download tag artifact
id: download-tag
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: tag
path: .github

- name: Set tag variable
run: |
if [[ "${{ steps.download-tag.outcome }}" == 'success' ]]; then
echo "TAG=$(<.github/tag)" >> $GITHUB_ENV
else
echo "TAG=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
fi
- name: Verify the tag
id: verify-tag
env:
tag: ${{ github.event.inputs.tag }}
run: |
tag_regex='^[0-9]+\.[0-9]+\.[0-9]+-[0-9]+$'
if [[ ! "$tag" =~ $tag_regex ]]; then
echo "::error::The provided tag ($tag) has incorrect format (attempted to match ${tag_regex})."
if [[ ! "$TAG" =~ $tag_regex ]]; then
echo "::error::The provided tag ($TAG) has incorrect format (attempted to match ${tag_regex})."
exit 1
fi
echo "release-version=${tag//-/.}" >> $GITHUB_OUTPUT
echo "release-version=${TAG//-/.}" >> $GITHUB_OUTPUT
- name: Check out the code
uses: actions/checkout@v4
Expand All @@ -87,12 +120,11 @@ jobs:
- name: Fetch DMG
id: fetch-dmg
if: ${{ github.event.inputs.release-type != 'public' }}
env:
DMG_NAME: duckduckgo-${{ steps.verify-tag.outputs.release-version }}.dmg
run: |
# Public release doesn't need fetching a DMG (it's already uploaded to S3)
if [[ "${{ github.event.inputs.release-type }}" != 'public' ]]; then
if [[ "${RELEASE_TYPE}" != 'public' ]]; then
DMG_URL="${{ vars.DMG_URL_ROOT }}${DMG_NAME}"
curl -fLSs -o "$DMG_NAME" "$DMG_URL"
fi
Expand Down Expand Up @@ -121,7 +153,6 @@ jobs:
env:
DMG_PATH: ${{ steps.fetch-dmg.outputs.dmg-path }}
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
RELEASE_TYPE: ${{ github.event.inputs.release-type }}
VERSION: ${{ steps.verify-tag.outputs.release-version }}
run: |
echo -n "$SPARKLE_PRIVATE_KEY" > sparkle_private_key
Expand Down Expand Up @@ -169,7 +200,6 @@ jobs:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_RELEASE_S3 }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_RELEASE_S3 }}
AWS_DEFAULT_REGION: ${{ vars.AWS_DEFAULT_REGION }}
RELEASE_TYPE: ${{ github.event.inputs.release-type }}
VERSION: ${{ steps.verify-tag.outputs.release-version }}
run: |
# Back up existing appcast2.xml
Expand All @@ -192,7 +222,7 @@ jobs:
- name: Update Asana for the release
id: update-asana
if: ${{ github.event.inputs.release-type != 'internal' }}
if: ${{ env.RELEASE_TYPE != 'internal' }}
continue-on-error: true
env:
ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
Expand All @@ -217,15 +247,12 @@ jobs:
echo "RELEASE_BUCKET_NAME=${{ vars.RELEASE_BUCKET_NAME }}" >> $GITHUB_ENV
echo "RELEASE_BUCKET_PREFIX=${{ vars.RELEASE_BUCKET_PREFIX }}" >> $GITHUB_ENV
echo "RELEASE_TASK_ID=${{ steps.task-id.outputs.task-id }}" >> $GITHUB_ENV
echo "TAG=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
echo "VERSION=${{ steps.verify-tag.outputs.release-version }}" >> $GITHUB_ENV
echo "WORKFLOW_URL=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_ENV
- name: Set up Asana templates
if: always()
id: asana-templates
env:
RELEASE_TYPE: ${{ github.event.inputs.release-type }}
run: |
if [[ ${{ steps.upload.outcome }} == "success" ]]; then
if [[ "${RELEASE_TYPE}" == "internal" ]]; then
Expand Down Expand Up @@ -264,7 +291,7 @@ jobs:

- name: Create Asana task to announce the release
id: create-announcement-task
if: ${{ github.event.inputs.release-type != 'internal' }}
if: ${{ env.RELEASE_TYPE != 'internal' }}
uses: ./.github/actions/asana-create-action-item
env:
html-notes: ${{ steps.update-asana.outputs.announcement-task-contents }}
Expand Down Expand Up @@ -328,7 +355,8 @@ jobs:

needs: [publish-to-sparkle]

if: ${{ github.event.inputs.release-type != 'internal' }}
# Run if release-type is provided (not empty) an is not internal
if: contains(github.event.inputs.release-type, '') == false && github.event.inputs.release-type != 'internal'

uses: duckduckgo/macos-browser/.github/workflows/create_variants.yml@main
secrets:
Expand Down
29 changes: 28 additions & 1 deletion .github/workflows/tag_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ on:
description: "Is this a pre-release? (a.k.a. internal release)"
required: true
type: boolean
internal-release-bump:
description: "Is this an internal release bump? (the subsequent internal release of the current week)"
required: false
default: false
type: boolean
secrets:
ASANA_ACCESS_TOKEN:
required: true
Expand All @@ -57,6 +62,7 @@ jobs:
BASE_BRANCH: ${{ inputs.base-branch || 'main' }}
BRANCH: ${{ inputs.branch || github.ref_name }}
prerelease: ${{ github.event.inputs.prerelease || inputs.prerelease }}
internal-release-bump: ${{ inputs.internal-release-bump }}

outputs:
tag: ${{ steps.create-tag.outputs.tag }}
Expand Down Expand Up @@ -84,6 +90,16 @@ jobs:
prerelease: ${{ env.prerelease }}
github-token: ${{ github.token }}

- name: Store created tag in a file artifact
run: echo ${{ steps.create-tag.outputs.tag }} > .github/tag

- name: Upload tag artifact
uses: actions/upload-artifact@v4
with:
name: tag
path: .github/tag
retention-days: 1

- name: Merge to base branch
id: merge
if: ${{ env.prerelease == 'true' }}
Expand All @@ -106,7 +122,7 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: |
gh api --method DELETE /repos/${{ github.repository }}/git/refs/heads/${{ env.BRANCH}}
gh api --method DELETE /repos/${{ github.repository }}/git/refs/heads/${{ env.BRANCH }}
- name: Set common environment variables
if: always()
Expand Down Expand Up @@ -163,6 +179,17 @@ jobs:
release-task-url: ${{ env.asana-task-url }}
template-name: ${{ steps.asana-failure-templates.outputs.task-template }}

- name: Create Publish DMG Release task on failure
id: create-publish-dmg-task-on-failure
if: failure() && env.internal-release-bump == 'true'
uses: ./.github/actions/asana-create-action-item
env:
ASANA_TASK_URL: ${{ env.asana-task-url }}
with:
access-token: ${{ secrets.ASANA_ACCESS_TOKEN }}
release-task-url: ${{ env.asana-task-url }}
template-name: run-publish-dmg-release

- name: Report failure
if: failure() || env.MERGE_OR_DELETE_FAILED == 'true'
uses: ./.github/actions/asana-log-message
Expand Down

0 comments on commit 676528e

Please sign in to comment.