Skip to content

Publish DMG Release

Publish DMG Release #3

name: Publish DMG Release
on:
workflow_dispatch:
inputs:
asana-task-url:
description: "Asana release task URL"
required: true
type: string
tag:
description: "Tag to publish"
required: true
type: string
jobs:
publish-to-sparkle:
name: Publish internal release to Sparkle
runs-on: macos-13-xlarge
timeout-minutes: 10
env:
SPARKLE_DIR: ${{ github.workspace }}/sparkle-updates
steps:
- 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})."
exit 1
fi
echo "tag-in-filename=${tag//-/.}" >> $GITHUB_OUTPUT
- name: Check out the code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Sparkle tools
env:
SPARKLE_URL: https://github.com/sparkle-project/Sparkle/releases/download/${{ vars.SPARKLE_VERSION }}/Sparkle-${{ vars.SPARKLE_VERSION }}.tar.xz
run: |
curl -fLSs $SPARKLE_URL | tar xJ bin
echo "${{ github.workspace }}/bin" >> $GITHUB_PATH
- name: Fetch DMG
id: fetch-dmg
env:
DMG_NAME: duckduckgo-${{ steps.verify-tag.outputs.tag-in-filename }}.dmg
run: |
DMG_URL="${{ vars.DMG_URL_ROOT }}${DMG_NAME}"
curl -fLSs -o "$DMG_NAME" "$DMG_URL"
echo "dmg-name=$DMG_NAME" >> $GITHUB_OUTPUT
echo "dmg-path=$DMG_NAME" >> $GITHUB_OUTPUT
- name: Extract Asana Task ID
id: task-id
uses: ./.github/actions/asana-extract-task-id
with:
task-url: ${{ github.event.inputs.asana-task-url }}
- name: Fetch release notes
env:
TASK_ID: ${{ steps.task-id.outputs.task-id }}
ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
run: |
curl -fLSs "https://app.asana.com/api/1.0/tasks/${TASK_ID}?opt_fields=notes" \
-H "Authorization: Bearer ${ASANA_ACCESS_TOKEN}" \
| jq -r .data.notes \
| ./scripts/extract_release_notes.sh > release_notes.txt
echo "RELEASE_NOTES_FILE=release_notes.txt" >> $GITHUB_ENV
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_$(<.xcode-version).app/Contents/Developer
- name: Generate appcast
id: appcast
env:
DMG_PATH: ${{ steps.fetch-dmg.outputs.dmg-path }}
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
run: |
echo -n "$SPARKLE_PRIVATE_KEY" > sparkle_private_key
chmod 600 sparkle_private_key
./scripts/appcast_manager/appcastManager.swift \
--release-to-internal-channel \
--dmg ${DMG_PATH} \
--release-notes release_notes.txt \
--key sparkle_private_key
appcast_patch_name="appcast2-${{ steps.verify-tag.outputs.tag-in-filename }}.patch"
mv -f ${{ env.SPARKLE_DIR }}/appcast_diff.txt ${{ env.SPARKLE_DIR }}/${appcast_patch_name}
echo "appcast-patch-name=${appcast_patch_name}" >> $GITHUB_OUTPUT
- name: Upload appcast diff artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.appcast.outputs.appcast-patch-name }}
path: ${{ env.SPARKLE_DIR }}/${{ steps.appcast.outputs.appcast-patch-name }}
- name: Upload to S3
id: upload
env:
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 }}
run: |
# Back up existing appcast2.xml
OLD_APPCAST_NAME=appcast2_old.xml
echo "OLD_APPCAST_NAME=${OLD_APPCAST_NAME}" >> $GITHUB_ENV
curl -fLSs "${{ vars.DMG_URL_ROOT }}appcast2.xml" --output "${OLD_APPCAST_NAME}"
# Upload files to S3
./scripts/upload_to_s3/upload_to_s3.sh --run --force
if [[ -f "${{ env.SPARKLE_DIR }}/uploaded_files_list.txt" ]]; then
echo "FILES_UPLOADED=$(awk '{ print "<li><code>"$1"</code></li>"; }' < ${{ env.SPARKLE_DIR }}/uploaded_files_list.txt | tr '\n' ' ')" >> $GITHUB_ENV
else
echo "FILES_UPLOADED='No files uploaded.'" >> $GITHUB_ENV
fi
- name: Set common environment variables
if: always()
env:
DMG_NAME: ${{ steps.fetch-dmg.outputs.dmg-name }}
run: |
echo "APPCAST_PATCH_NAME=${{ steps.appcast.outputs.appcast-patch-name }}" >> $GITHUB_ENV
echo "DMG_NAME=${DMG_NAME}" >> $GITHUB_ENV
echo "DMG_URL=${{ vars.DMG_URL_ROOT }}${DMG_NAME}" >> $GITHUB_ENV
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 "WORKFLOW_URL=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> $GITHUB_ENV
- name: Set up Asana templates
if: always()
id: asana-templates
run: |
if [[ ${{ steps.upload.outcome }} == "success" ]]; then
echo "task-template=validate-check-for-updates-internal" >> $GITHUB_OUTPUT
echo "comment-template=validate-check-for-updates-internal" >> $GITHUB_OUTPUT
echo "release-task-comment-template=internal-release-complete" >> $GITHUB_OUTPUT
else
echo "task-template=appcast-failed" >> $GITHUB_OUTPUT
echo "comment-template=appcast-failed" >> $GITHUB_OUTPUT
fi
- name: Create Asana task
id: create-task
if: always()
uses: ./.github/actions/asana-create-action-item
with:
access-token: ${{ secrets.ASANA_ACCESS_TOKEN }}
release-task-url: ${{ github.event.inputs.asana-task-url }}
template-name: ${{ steps.asana-templates.outputs.task-template }}
- name: Upload patch to the Asana task
id: upload-patch
if: success()
uses: ./.github/actions/asana-upload
with:
access-token: ${{ secrets.ASANA_ACCESS_TOKEN }}
file-name: ${{ env.SPARKLE_DIR }}/${{ steps.appcast.outputs.appcast-patch-name }}
task-id: ${{ steps.create-task.outputs.new-task-id }}
- name: Upload old appcast file to the Asana task
id: upload-old-appcast
if: success()
uses: ./.github/actions/asana-upload
with:
access-token: ${{ secrets.ASANA_ACCESS_TOKEN }}
file-name: ${{ env.OLD_APPCAST_NAME }}
task-id: ${{ steps.create-task.outputs.new-task-id }}
- name: Upload release notes to the Asana task
id: upload-release-notes
if: success()
uses: ./.github/actions/asana-upload
with:
access-token: ${{ secrets.ASANA_ACCESS_TOKEN }}
file-name: ${{ env.RELEASE_NOTES_FILE }}
task-id: ${{ steps.create-task.outputs.new-task-id }}
- name: Report status
if: always()
uses: ./.github/actions/asana-log-message
env:
ASSIGNEE_ID: ${{ steps.create-task.outputs.assignee-id }}
TASK_ID: ${{ steps.create-task.outputs.new-task-id }}
with:
access-token: ${{ secrets.ASANA_ACCESS_TOKEN }}
task-url: ${{ github.event.inputs.asana-task-url }}
template-name: ${{ steps.asana-templates.outputs.comment-template }}
- name: Add a comment to the release task
if: success()
uses: ./.github/actions/asana-add-comment
with:
access-token: ${{ secrets.ASANA_ACCESS_TOKEN }}
task-url: ${{ github.event.inputs.asana-task-url }}
template-name: internal-release-complete