mirror of
https://github.com/bitwarden/android.git
synced 2026-02-04 11:41:32 -06:00
294 lines
12 KiB
YAML
294 lines
12 KiB
YAML
name: Create GitHub Release
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
artifact-run-id:
|
|
description: "GitHub Action Run ID containing artifacts"
|
|
required: true
|
|
type: string
|
|
release-ticket-id:
|
|
description: "Release Ticket ID - e.g. RELEASE-1762"
|
|
required: true
|
|
type: string
|
|
|
|
env:
|
|
ARTIFACTS_PATH: artifacts
|
|
|
|
jobs:
|
|
create-release:
|
|
name: Create GitHub Release
|
|
runs-on: ubuntu-24.04
|
|
permissions:
|
|
contents: write
|
|
id-token: write
|
|
|
|
steps:
|
|
- name: Check out repository
|
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: true
|
|
|
|
- name: Log inputs to job summary
|
|
uses: ./.github/actions/log-inputs
|
|
with:
|
|
inputs: ${{ toJson(inputs) }}
|
|
|
|
- name: Get branch from workflow run
|
|
id: get_release_branch
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
ARTIFACT_RUN_ID: ${{ inputs.artifact-run-id }}
|
|
run: |
|
|
workflow_data=$(gh run view "$ARTIFACT_RUN_ID" --json headBranch,workflowName)
|
|
release_branch=$(echo "$workflow_data" | jq -r .headBranch)
|
|
workflow_name=$(echo "$workflow_data" | jq -r .workflowName)
|
|
|
|
# branch protection check
|
|
if [[ "$release_branch" != "main" && ! "$release_branch" =~ ^release/ ]]; then
|
|
echo "::error::Branch '$release_branch' is not 'main' or a release branch starting with 'release/'. Releases must be created from protected branches."
|
|
exit 1
|
|
fi
|
|
|
|
echo "🔖 Release branch: $release_branch"
|
|
echo "🔖 Workflow name: $workflow_name"
|
|
echo "release_branch=$release_branch" >> "$GITHUB_OUTPUT"
|
|
echo "workflow_name=$workflow_name" >> "$GITHUB_OUTPUT"
|
|
|
|
case "$workflow_name" in
|
|
*"Password Manager"* | "Build")
|
|
app_name="Password Manager"
|
|
app_name_suffix="bwpm"
|
|
;;
|
|
*"Authenticator"*)
|
|
app_name="Authenticator"
|
|
app_name_suffix="bwa"
|
|
;;
|
|
*)
|
|
echo "::error::Unknown workflow name: $workflow_name"
|
|
exit 1
|
|
;;
|
|
esac
|
|
echo "🔖 App name: $app_name"
|
|
echo "🔖 App name suffix: $app_name_suffix"
|
|
echo "app_name=$app_name" >> "$GITHUB_OUTPUT"
|
|
echo "app_name_suffix=$app_name_suffix" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Get version info from run logs and set release tag name
|
|
id: get_release_info
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
ARTIFACT_RUN_ID: ${{ inputs.artifact-run-id }}
|
|
_APP_NAME_SUFFIX: ${{ steps.get_release_branch.outputs.app_name_suffix }}
|
|
run: |
|
|
workflow_log=$(gh run view "$ARTIFACT_RUN_ID" --log)
|
|
|
|
version_number_with_trailing_dot=$(grep -m 1 "Setting version code to" <<< "$workflow_log" | sed 's/.*Setting version code to //')
|
|
version_number=${version_number_with_trailing_dot%.} # remove trailing dot
|
|
|
|
version_name_with_trailing_dot=$(grep -m 1 "Setting version name to" <<< "$workflow_log" | sed 's/.*Setting version name to //')
|
|
version_name=${version_name_with_trailing_dot%.} # remove trailing dot
|
|
|
|
if [[ -z "$version_name" ]]; then
|
|
echo "::warning::Version name not found. Using default value - 0.0.0"
|
|
version_name="0.0.0"
|
|
else
|
|
echo "✅ Found version name: $version_name"
|
|
fi
|
|
|
|
if [[ -z "$version_number" ]]; then
|
|
echo "::warning::Version number not found. Using default value - 0"
|
|
version_number="0"
|
|
else
|
|
echo "✅ Found version number: $version_number"
|
|
fi
|
|
|
|
echo "version_number=$version_number" >> "$GITHUB_OUTPUT"
|
|
echo "version_name=$version_name" >> "$GITHUB_OUTPUT"
|
|
|
|
tag_name="v$version_name-$_APP_NAME_SUFFIX" # e.g. v2025.6.0-bwpm
|
|
echo "🔖 New tag name: $tag_name"
|
|
echo "tag_name=$tag_name" >> "$GITHUB_OUTPUT"
|
|
|
|
last_release_tag=$(git tag -l --sort=-authordate | grep "$_APP_NAME_SUFFIX" | head -n 1)
|
|
echo "🔖 Last release tag: $last_release_tag"
|
|
echo "last_release_tag=$last_release_tag" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Download artifacts
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
ARTIFACT_RUN_ID: ${{ inputs.artifact-run-id }}
|
|
run: |
|
|
gh run download "$ARTIFACT_RUN_ID" -D "$ARTIFACTS_PATH"
|
|
file_count=$(find "$ARTIFACTS_PATH" -type f | wc -l)
|
|
echo "Downloaded $file_count file(s)."
|
|
if [ "$file_count" -gt 0 ]; then
|
|
echo "Downloaded files:"
|
|
find "$ARTIFACTS_PATH" -type f
|
|
fi
|
|
|
|
# Files that won't be included in any release
|
|
files_to_remove=(
|
|
"com.x8bit.bitwarden.aab"
|
|
"com.x8bit.bitwarden.aab-sha256.txt"
|
|
|
|
"com.x8bit.bitwarden.beta.apk"
|
|
"com.x8bit.bitwarden.beta.apk-sha256.txt"
|
|
"com.x8bit.bitwarden.beta.aab"
|
|
"com.x8bit.bitwarden.beta.aab-sha256.txt"
|
|
|
|
"com.x8bit.bitwarden.beta-fdroid.apk"
|
|
"com.x8bit.bitwarden.beta-fdroid.apk-sha256.txt"
|
|
|
|
"com.x8bit.bitwarden.dev.apk"
|
|
"com.x8bit.bitwarden.dev.apk-sha256.txt"
|
|
|
|
"com.bitwarden.authenticator.aab"
|
|
"authenticator-android-aab-sha256.txt"
|
|
)
|
|
|
|
for file in "${files_to_remove[@]}"; do
|
|
find "$ARTIFACTS_PATH" -name "$file" -type f -delete
|
|
done
|
|
echo "🔖 Removed internal artifacts."
|
|
echo ""
|
|
echo "🔖 Files to be included in the release:"
|
|
find "$ARTIFACTS_PATH" -type f
|
|
|
|
- name: Log in to Azure
|
|
uses: bitwarden/gh-actions/azure-login@main
|
|
with:
|
|
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
|
|
client_id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
|
|
- name: Get Azure Key Vault secrets
|
|
id: get-kv-secrets
|
|
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
|
with:
|
|
keyvault: gh-android
|
|
secrets: "JIRA-API-EMAIL,JIRA-API-TOKEN"
|
|
|
|
- name: Log out from Azure
|
|
uses: bitwarden/gh-actions/azure-logout@main
|
|
|
|
- name: Get product release notes
|
|
id: get_release_notes
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
ARTIFACT_RUN_ID: ${{ inputs.artifact-run-id }}
|
|
_VERSION_NAME: ${{ steps.get_release_info.outputs.version_name }}
|
|
_RELEASE_TICKET_ID: ${{ inputs.release-ticket-id }}
|
|
_JIRA_API_EMAIL: ${{ steps.get-kv-secrets.outputs.JIRA-API-EMAIL }}
|
|
_JIRA_API_TOKEN: ${{ steps.get-kv-secrets.outputs.JIRA-API-TOKEN }}
|
|
run: |
|
|
echo "Getting product release notes..."
|
|
# capture output and exit code so this step continues even if we can't retrieve release notes.
|
|
script_exit_code=0
|
|
product_release_notes=$(python .github/scripts/jira-get-release-notes/jira_release_notes.py "$_RELEASE_TICKET_ID" "$_JIRA_API_EMAIL" "$_JIRA_API_TOKEN") || script_exit_code=$?
|
|
echo "--------------------------------"
|
|
|
|
if [[ $script_exit_code -ne 0 || -z "$product_release_notes" ]]; then
|
|
echo "Script Output: $product_release_notes"
|
|
echo "::warning::Failed to fetch release notes from Jira. Check script logs for more details."
|
|
product_release_notes="<insert product release notes here>"
|
|
else
|
|
echo "✅ Product release notes:"
|
|
echo "$product_release_notes"
|
|
fi
|
|
|
|
echo "$product_release_notes" > product_release_notes.txt
|
|
|
|
- name: Create Release
|
|
id: create_release
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
_APP_NAME: ${{ steps.get_release_branch.outputs.app_name }}
|
|
_VERSION_NAME: ${{ steps.get_release_info.outputs.version_name }}
|
|
_VERSION_NUMBER: ${{ steps.get_release_info.outputs.version_number }}
|
|
_TARGET_COMMIT: ${{ steps.get_release_branch.outputs.release_branch }}
|
|
_TAG_NAME: ${{ steps.get_release_info.outputs.tag_name }}
|
|
_LAST_RELEASE_TAG: ${{ steps.get_release_info.outputs.last_release_tag }}
|
|
run: |
|
|
is_latest_release=false
|
|
if [[ "$_APP_NAME" == "Password Manager" ]]; then
|
|
is_latest_release=true
|
|
fi
|
|
|
|
echo "⌛️ Creating release for $_APP_NAME $_VERSION_NAME ($_VERSION_NUMBER) on $_TARGET_COMMIT"
|
|
release_url=$(gh release create "$_TAG_NAME" \
|
|
--title "$_APP_NAME $_VERSION_NAME ($_VERSION_NUMBER)" \
|
|
--target "$_TARGET_COMMIT" \
|
|
--generate-notes \
|
|
--notes-start-tag "$_LAST_RELEASE_TAG" \
|
|
--latest=$is_latest_release \
|
|
--draft \
|
|
"$ARTIFACTS_PATH/*/*")
|
|
|
|
# Extract release tag from URL
|
|
release_id_from_url=$(echo "$release_url" | sed 's/.*\/tag\///')
|
|
echo "release_id_from_url=$release_id_from_url" >> "$GITHUB_OUTPUT"
|
|
echo "url=$release_url" >> "$GITHUB_OUTPUT"
|
|
|
|
echo "✅ Release created: $release_url"
|
|
echo "🔖 Release ID from URL: $release_id_from_url"
|
|
|
|
- name: Update Release Description
|
|
id: update_release_description
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
ARTIFACT_RUN_ID: ${{ inputs.artifact-run-id }}
|
|
_VERSION_NAME: ${{ steps.get_release_info.outputs.version_name }}
|
|
_RELEASE_ID: ${{ steps.create_release.outputs.release_id_from_url }}
|
|
run: |
|
|
echo "Getting current release body. Release ID: $_RELEASE_ID"
|
|
current_body=$(gh release view "$_RELEASE_ID" --json body --jq .body)
|
|
|
|
product_release_notes=$(cat product_release_notes.txt)
|
|
|
|
# Update release description with product release notes and builds source
|
|
updated_body="# Overview
|
|
${product_release_notes}
|
|
|
|
${current_body}
|
|
**Builds Source:** https://github.com/${{ github.repository }}/actions/runs/$ARTIFACT_RUN_ID"
|
|
|
|
new_release_url=$(gh release edit "$_RELEASE_ID" --notes "$updated_body")
|
|
|
|
# draft release links change after editing
|
|
echo "release_url=$new_release_url" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Add Release Summary
|
|
env:
|
|
_RELEASE_TAG: ${{ steps.get_release_info.outputs.tag_name }}
|
|
_LAST_RELEASE_TAG: ${{ steps.get_release_info.outputs.last_release_tag }}
|
|
_VERSION_NAME: ${{ steps.get_release_info.outputs.version_name }}
|
|
_VERSION_NUMBER: ${{ steps.get_release_info.outputs.version_number }}
|
|
_RELEASE_BRANCH: ${{ steps.get_release_branch.outputs.release_branch }}
|
|
_RELEASE_URL: ${{ steps.update_release_description.outputs.release_url }}
|
|
run: |
|
|
{
|
|
echo "# :fish_cake: Release ready at:"
|
|
echo "$_RELEASE_URL"
|
|
echo ""
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
if [[ "$_VERSION_NAME" == "0.0.0" || "$_VERSION_NUMBER" == "0" ]]; then
|
|
{
|
|
echo "> [!CAUTION]"
|
|
echo "> Version name or number wasn't previously found and a default value was used. You'll need to manually update the release Title, Tag and Description, specifically, the \"Full Changelog\" link."
|
|
echo ""
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
fi
|
|
|
|
{
|
|
echo ":clipboard: Confirm that the defined GitHub Release options are correct:"
|
|
echo " * :bookmark: New tag name: \`$_RELEASE_TAG\`"
|
|
echo " * :palm_tree: Target branch: \`$_RELEASE_BRANCH\`"
|
|
echo " * :ocean: Previous tag set in the description \"Full Changelog\" link: \`$_LAST_RELEASE_TAG\`"
|
|
echo " * :white_check_mark: Description has automated release notes and they match the commits in the release branch"
|
|
echo "> [!NOTE]"
|
|
echo "> Commits directly pushed to branches without a Pull Request won't appear in the automated release notes."
|
|
} >> "$GITHUB_STEP_SUMMARY"
|