chore: appcast generation #18
This file contains hidden or 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
name: Release | |
on: | |
push: | |
tags: | |
- '*' | |
workflow_dispatch: | |
inputs: | |
version: | |
description: 'Version number (e.g. v1.2.3)' | |
required: true | |
permissions: | |
contents: write | |
# Necessary for GCP authentication (https://github.com/google-github-actions/setup-gcloud#usage) | |
id-token: write | |
jobs: | |
release: | |
runs-on: ${{ github.repository_owner == 'coder' && 'windows-latest-16-cores' || 'windows-latest' }} | |
outputs: | |
version: ${{ steps.version.outputs.VERSION }} | |
timeout-minutes: 15 | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup .NET | |
uses: actions/setup-dotnet@v4 | |
with: | |
dotnet-version: '8.0.x' | |
# Necessary for signing Windows binaries. | |
- name: Setup Java | |
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 | |
with: | |
distribution: "zulu" | |
java-version: "11.0" | |
- name: Get version from tag | |
id: version | |
shell: pwsh | |
run: | | |
$ErrorActionPreference = "Stop" | |
if ($env:INPUT_VERSION) { | |
$tag = $env:INPUT_VERSION | |
} else { | |
$tag = $env:GITHUB_REF -replace 'refs/tags/','' | |
} | |
if ($tag -notmatch '^v\d+\.\d+\.\d+$') { | |
throw "Version must be in format v1.2.3, got $tag" | |
} | |
$version = $tag -replace '^v','' | |
$assemblyVersion = "$($version).0" | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "VERSION=$version" | |
Add-Content -Path $env:GITHUB_OUTPUT -Value "ASSEMBLY_VERSION=$assemblyVersion" | |
Write-Host "Version: $version" | |
Write-Host "Assembly version: $assemblyVersion" | |
env: | |
INPUT_VERSION: ${{ inputs.version }} | |
# Setup GCloud for signing Windows binaries. | |
- name: Authenticate to Google Cloud | |
id: gcloud_auth | |
uses: google-github-actions/auth@71f986410dfbc7added4569d411d040a91dc6935 # v2.1.8 | |
with: | |
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_ID_PROVIDER }} | |
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }} | |
token_format: "access_token" | |
- name: Install gcloud | |
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # 2.1.4 | |
- name: Install wix | |
shell: pwsh | |
run: | | |
$ErrorActionPreference = "Stop" | |
& dotnet.exe tool install --global wix --version 5.0.2 | |
if ($LASTEXITCODE -ne 0) { throw "Failed to install wix" } | |
foreach ($ext in @("WixToolset.Bal.wixext/5.0.2", "WixToolset.Netfx.wixext/5.0.2", "WixToolset.UI.wixext/5.0.2", "WixToolset.Util.wixext/5.0.2")) { | |
& wix.exe extension add -g $ext | |
if ($LASTEXITCODE -ne 0) { throw "Failed to add wix extension $ext" } | |
} | |
- name: scripts/Release.ps1 | |
id: release | |
shell: pwsh | |
run: | | |
$ErrorActionPreference = "Stop" | |
$env:EV_CERTIFICATE_PATH = Join-Path $env:TEMP "ev_cert.pem" | |
Set-Content -Path $env:EV_CERTIFICATE_PATH -Value $env:EV_SIGNING_CERT | |
$env:JSIGN_PATH = Join-Path $env:TEMP "jsign-6.0.jar" | |
Invoke-WebRequest -Uri "https://github.com/ebourg/jsign/releases/download/6.0/jsign-6.0.jar" -OutFile $env:JSIGN_PATH | |
& ./scripts/Release.ps1 ` | |
-version ${{ steps.version.outputs.VERSION }} ` | |
-assemblyVersion ${{ steps.version.outputs.ASSEMBLY_VERSION }} | |
if ($LASTEXITCODE -ne 0) { throw "Failed to publish" } | |
env: | |
EV_SIGNING_CERT: ${{ secrets.EV_SIGNING_CERT }} | |
EV_KEYSTORE: ${{ secrets.EV_KEYSTORE }} | |
EV_KEY: ${{ secrets.EV_KEY }} | |
EV_TSA_URL: ${{ secrets.EV_TSA_URL }} | |
GCLOUD_ACCESS_TOKEN: ${{ steps.gcloud_auth.outputs.access_token }} | |
- name: Upload artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: publish | |
path: .\publish\ | |
- name: Create release | |
uses: softprops/action-gh-release@v2 | |
if: startsWith(github.ref, 'refs/tags/') | |
with: | |
name: Release ${{ steps.version.outputs.VERSION }} | |
generate_release_notes: true | |
# We currently only release the bootstrappers, not the MSIs. | |
files: | | |
${{ steps.release.outputs.X64_OUTPUT_PATH }} | |
${{ steps.release.outputs.ARM64_OUTPUT_PATH }} | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Update appcast | |
if: startsWith(github.ref, 'refs/tags/') | |
shell: pwsh | |
$ErrorActionPreference = "Stop" | |
$keyPath = Join-Path $env:TEMP "appcast-key.pem" | |
$key = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($env:APPCAST_SIGNATURE_KEY_BASE64)) | |
Set-Content -Path $keyPath -Value $key | |
$oldAppCastPath = Join-Path $env:TEMP "appcast.old.xml" | |
& gsutil cp $env:APPCAST_GCS_URI $oldAppCastPath | |
if ($LASTEXITCODE -ne 0) { throw "Failed to download appcast" } | |
$newAppCastPath = Join-Path $env:TEMP "appcast.new.xml" | |
$newAppCastSignaturePath = $newAppCastPath + ".signature" | |
& ./scripts/Update-AppCast.ps1 ` | |
-tag "${{ github.ref_name }}" ` | |
-version "${{ steps.version.outputs.VERSION }}" ` | |
-channel stable ` | |
-x64Path "${{ steps.release.outputs.X64_OUTPUT_PATH }}" ` | |
-arm64Path "${{ steps.release.outputs.ARM64_OUTPUT_PATH }}" ` | |
-keyPath $keyPath ` | |
-inputAppCastPath $oldAppCastPath ` | |
-outputAppCastPath $newAppCastPath ` | |
-outputAppCastSignaturePath $newAppCastSignaturePath | |
if ($LASTEXITCODE -ne 0) { throw "Failed to generate new appcast" } | |
& gsutil cp $newAppCastPath $env:APPCAST_GCS_URI | |
if ($LASTEXITCODE -ne 0) { throw "Failed to upload new appcast" } | |
& gsutil cp $newAppCastSignaturePath $env:APPCAST_SIGNATURE_GCS_URI | |
if ($LASTEXITCODE -ne 0) { throw "Failed to upload new appcast signature" } | |
env: | |
APPCAST_GCS_URI: gs://releases.coder.com/coder-desktop/windows/appcast.xml | |
APPCAST_SIGNATURE_GCS_URI: gs://releases.coder.com/coder-desktop/windows/appcast.xml.signature | |
APPCAST_SIGNATURE_KEY_BASE64: ${{ secrets.APPCAST_SIGNATURE_KEY_BASE64 }} | |
GCLOUD_ACCESS_TOKEN: ${{ steps.gcloud_auth.outputs.access_token }} | |
winget: | |
runs-on: depot-windows-latest | |
needs: release | |
steps: | |
- name: Sync fork | |
run: gh repo sync cdrci/winget-pkgs -b master | |
env: | |
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }} | |
- name: Checkout | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
fetch-depth: 0 | |
# If the event that triggered the build was an annotated tag (which our | |
# tags are supposed to be), actions/checkout has a bug where the tag in | |
# question is only a lightweight tag and not a full annotated tag. This | |
# command seems to fix it. | |
# https://github.com/actions/checkout/issues/290 | |
- name: Fetch git tags | |
run: git fetch --tags --force | |
- name: Install wingetcreate | |
run: | | |
Invoke-WebRequest https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe | |
- name: Submit updated manifest to winget-pkgs | |
run: | | |
$version = "${{ needs.release.outputs.version }}" | |
$release_assets = gh release view --repo coder/coder-desktop-windows "v${version}" --json assets | ` | |
ConvertFrom-Json | |
# Get the installer URLs from the release assets. | |
$amd64_installer_url = $release_assets.assets | ` | |
Where-Object name -Match ".*-x64.exe$" | ` | |
Select -ExpandProperty url | |
$arm64_installer_url = $release_assets.assets | ` | |
Where-Object name -Match ".*-arm64.exe$" | ` | |
Select -ExpandProperty url | |
echo "amd64 Installer URL: ${amd64_installer_url}" | |
echo "arm64 Installer URL: ${arm64_installer_url}" | |
echo "Package version: ${version}" | |
.\wingetcreate.exe update Coder.CoderDesktop ` | |
--submit ` | |
--version "${version}" ` | |
--urls "${amd64_installer_url}" "${arm64_installer_url}" ` | |
--token "$env:WINGET_GH_TOKEN" | |
env: | |
# For gh CLI: | |
GH_TOKEN: ${{ github.token }} | |
# For wingetcreate. We need a real token since we're pushing a commit | |
# to GitHub and then making a PR in a different repo. | |
WINGET_GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }} | |
- name: Comment on PR | |
run: | | |
# wait 30 seconds | |
Start-Sleep -Seconds 30.0 | |
# Find the PR that wingetcreate just made. | |
$version = "${{ needs.release.outputs.version }}" | |
$pr_list = gh pr list --repo microsoft/winget-pkgs --search "author:cdrci Coder.CoderDesktop version ${version}" --limit 1 --json number | ` | |
ConvertFrom-Json | |
$pr_number = $pr_list[0].number | |
gh pr comment --repo microsoft/winget-pkgs "${pr_number}" --body "🤖 cc: @deansheather @matifali" | |
env: | |
# For gh CLI. We need a real token since we're commenting on a PR in a | |
# different repo. | |
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }} |