Release nightly #65
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
name: Release nightly | |
on: | |
push: | |
branches: | |
- "**" | |
pull_request: | |
branches: | |
- main | |
schedule: | |
- cron: 0 2 * * * | |
workflow_dispatch: {} | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref_name }} | |
cancel-in-progress: true | |
permissions: | |
contents: write | |
jobs: | |
make-draft-release: | |
name: make draft release | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Get current date | |
id: date | |
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Delete existing nightly build | |
if: github.ref_name == 'main' && github.event_name != 'pull_request' | |
run: | | |
gh release delete nightly-$date \ | |
--yes \ | |
--cleanup-tag \ | |
|| true | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
- name: Create nightly build draft | |
if: github.ref_name == 'main' && github.event_name != 'pull_request' | |
run: | | |
gh release create nightly-$date \ | |
--draft \ | |
--title "Nightly build $date" | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
outputs: | |
date: ${{ env.date }} | |
build-app: | |
name: build app | |
needs: | |
- make-draft-release | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- os: ubuntu-20.04 | |
arch: arm64 | |
concurrency: linux-arm64 | |
- os: ubuntu-20.04 | |
arch: x64 | |
concurrency: linux-amd64 | |
- os: macos-14 | |
arch: arm64 | |
concurrency: macos | |
- os: macos-14 | |
arch: x64 | |
concurrency: macos | |
- os: windows-2022 | |
arch: x64 | |
concurrency: windows | |
runs-on: ${{ matrix.os }} | |
environment: ${{ github.ref_name == 'main' && 'test-signing' || null }} | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ matrix.concurrency }} | |
steps: | |
- name: Checkout freelensapp/freelens | |
uses: actions/checkout@v4 | |
with: | |
repository: freelensapp/freelens | |
ref: main | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
path: tmp/nightly-builds | |
- name: Save current revision | |
id: current_revision | |
run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | |
- name: Setup node | |
uses: actions/setup-node@v4 | |
with: | |
node-version-file: .nvmrc | |
- name: Get npm cache directory | |
shell: bash | |
run: echo "npm_cache_dir=$(npm config get cache)" >> ${GITHUB_ENV} | |
- name: Use npm cache | |
uses: actions/cache@v4 | |
with: | |
path: ${{ env.npm_cache_dir }} | |
key: ${{ matrix.os }}-${{ matrix.arch }}-node-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ matrix.os }}-${{ matrix.arch }}-node- | |
- name: Install dependencies (Linux) | |
if: runner.os == 'Linux' | |
uses: nick-fields/retry@v3 | |
with: | |
timeout_minutes: 20 | |
max_attempts: 3 | |
retry_on: any | |
command: | | |
sudo apt-get install -y --no-install-recommends \ | |
gcc-aarch64-linux-gnu g++-aarch64-linux-gnu | |
- name: Install dependencies (macOS) | |
if: runner.os == 'macOS' | |
uses: nick-fields/retry@v3 | |
with: | |
timeout_minutes: 20 | |
max_attempts: 3 | |
retry_on: any | |
command: brew install bash python-setuptools | |
- name: Install dependencies (Windows) | |
if: runner.os == 'Windows' | |
uses: nick-fields/retry@v3 | |
with: | |
timeout_minutes: 20 | |
max_attempts: 3 | |
retry_on: any | |
command: choco install yq | |
- name: Tweak package for nightly build | |
shell: bash | |
run: | | |
yq -pj -oj -i ".version += \"-$tag\"" freelens/package.json | |
cp -f tmp/nightly-builds/apt/* freelens/build/apt | |
yq -pj -oj -i '.build.deb.fpm += ["./build/apt/freelens-nightly-builds.asc=/etc/apt/keyrings/freelens-nightly-builds.asc", "./build/apt/freelens-nightly-builds.sources=/etc/apt/sources.list.d/freelens-nightly-builds.sources"]' freelens/package.json | |
env: | |
tag: nightly-${{ needs.make-draft-release.outputs.date }} | |
- name: Install NPM dependencies | |
uses: nick-fields/retry@v3 | |
with: | |
timeout_minutes: 20 | |
max_attempts: 3 | |
retry_on: any | |
command: npm ci | |
- name: Rebuild for arch (Linux arm64) | |
if: runner.os == 'Linux' && matrix.arch == 'arm64' | |
run: npm run rebuild -- -- -a arm64 | |
env: | |
CC: aarch64-linux-gnu-gcc | |
CXX: aarch64-linux-gnu-g++ | |
- name: Monkey patch FPM arguments for RPM (Linux arm64) | |
if: runner.os == 'Linux' && matrix.arch == 'arm64' | |
run: | | |
sed -i 's/\? "aarch64" : "arm64"/|| targetName === "rpm" &/' node_modules/builder-util/out/arch.js | |
- name: Rebuild for arch (macOS x64) | |
if: runner.os == 'macOS' && matrix.arch == 'x64' | |
run: npm run rebuild -- -- -a x64 | |
- name: Build NPM packages (macOS x64, Linux arm64) | |
if: runner.os == 'macOS' && matrix.arch == 'x64' || runner.os == 'Linux' && matrix.arch == 'arm64' | |
run: npm run build | |
env: | |
DOWNLOAD_ALL_ARCHITECTURES: "true" | |
- name: Build NPM packages (macOS arm64, Linux x64, Windows) | |
if: runner.os == 'macOS' && matrix.arch == 'arm64' || runner.os == 'Linux' && matrix.arch == 'x64' || runner.os == 'Windows' | |
run: npm run build | |
- name: Build Electron app (macOS) | |
if: runner.os == 'macOS' | |
uses: nick-fields/retry@v3 | |
with: | |
timeout_minutes: 20 | |
max_attempts: 3 | |
retry_on: any | |
command: | | |
for var in APPLEID APPLEIDPASS APPLETEAMID CSC_LINK CSC_KEY_PASSWORD CSC_INSTALLER_LINK CSC_INSTALLER_KEY_PASSWORD; do | |
test -n "${!var}" || unset $var | |
done | |
npm run build:app -- -- -- \ | |
dmg pkg \ | |
--publish never \ | |
--${{ matrix.arch }} | |
env: | |
APPLEID: ${{ secrets.APPLEID }} | |
APPLEIDPASS: ${{ secrets.APPLEIDPASS }} | |
APPLETEAMID: ${{ secrets.APPLETEAMID }} | |
CSC_LINK: ${{ secrets.CSC_LINK }} | |
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} | |
CSC_INSTALLER_LINK: ${{ secrets.CSC_INSTALLER_LINK }} | |
CSC_INSTALLER_KEY_PASSWORD: ${{ secrets.CSC_INSTALLER_KEY_PASSWORD }} | |
- name: Notarize PKG (macOS) | |
if: runner.os == 'macOS' | |
uses: nick-fields/retry@v3 | |
with: | |
timeout_minutes: 20 | |
max_attempts: 3 | |
retry_on: any | |
command: | | |
if [[ -n $APPLEID && -n $APPLEIDPASS && -n $APPLETEAMID ]]; then | |
pkgname=$(ls -1 freelens/dist/Freelens*.pkg | head -n1) | |
auth="--apple-id $APPLEID --password $APPLEIDPASS --team-id $APPLETEAMID" | |
xcrun notarytool submit $pkgname $auth --wait 2>&1 | tee freelens/dist/notarytool.log | |
uuid=$(awk '/id: / { print $2; exit; }' freelens/dist/notarytool.log) | |
sleep 60 | |
if [[ -n $uuid ]]; then | |
xcrun notarytool log $uuid $auth | |
xcrun stapler staple $pkgname | |
fi | |
fi | |
env: | |
APPLEID: ${{ secrets.APPLEID }} | |
APPLEIDPASS: ${{ secrets.APPLEIDPASS }} | |
APPLETEAMID: ${{ secrets.APPLETEAMID }} | |
- name: Build Electron app (Linux) | |
if: runner.os == 'Linux' | |
run: | | |
npm run build:app -- -- -- \ | |
AppImage deb rpm \ | |
--publish never \ | |
--${{ matrix.arch }} | |
- name: Build Electron app (Windows x64) | |
if: runner.os == 'Windows' && matrix.arch == 'x64' | |
shell: bash | |
run: | | |
for var in CSC_LINK CSC_KEY_PASSWORD; do | |
test -n "${!var}" || unset $var | |
done | |
npm run build:app -- -- -- \ | |
msi nsis \ | |
--publish never \ | |
--${{ matrix.arch }} | |
env: | |
CSC_LINK: ${{ secrets.WIN_CSC_LINK }} | |
CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }} | |
- name: Azure Trusted Signing (Windows x64) | |
if: runner.os == 'Windows' && matrix.arch == 'x64' && github.ref_name == 'main' && github.event_name != 'pull_request' | |
uses: azure/trusted-signing-action@v0.5.1 | |
with: | |
azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} | |
endpoint: ${{ vars.AZURE_ENDPOINT }} | |
trusted-signing-account-name: ${{ vars.AZURE_CODE_SIGNING_NAME }} | |
certificate-profile-name: ${{ vars.AZURE_CERT_PROFILE_NAME }} | |
files-folder: ${{ github.workspace }}\freelens\dist | |
files-folder-filter: exe,msi | |
- name: Tweak binaries | |
shell: bash | |
run: | | |
find . -name '*pty.node' -print0 | xargs -0 file | |
rm -f freelens/dist/*.blockmap | |
- name: Normalize filenames before upload | |
shell: bash | |
run: | | |
perl << 'END' | |
chdir "freelens/dist" or die $!; | |
my %arch = (x64 => "amd64", arm64 => "arm64"); | |
my $arch = $arch{$ENV{ARCH}}; | |
while (<Freelens*>) { | |
my $src = $_; | |
s/ Setup /-/; | |
s/[ _]/-/g; | |
if (/\.(dmg|exe|msi|pkg)$/ && !/-(amd64|arm64)\./) { | |
s/\.(dmg|exe|msi|pkg)$/-$arch.$1/; | |
} | |
s/[.-](aarch64|arm64)/-arm64/; | |
s/[.-](amd64|x86-64)/-amd64/; | |
s/-(amd64|arm64).(dmg|pkg)$/-macos-$1.$2/; | |
s/-(amd64|arm64).(AppImage|deb|flatpak|rpm|snap)$/-linux-$1.$2/; | |
s/-(amd64|arm64).(exe|msi|)$/-windows-$1.$2/; | |
my $dst = $_; | |
if ($src ne $dst) { | |
print "rename $src to $dst\n"; | |
rename $src, $dst or die $!; | |
} | |
} | |
END | |
env: | |
ARCH: ${{ matrix.arch }} | |
- name: Make checksums for binaries (Linux, Windows) | |
if: runner.os == 'Linux' || runner.os == 'Windows' | |
shell: bash | |
run: | | |
for f in freelens/dist/Freelens*.*; do | |
sha256sum "$f" | tee "$f.sha256" | |
done | |
- name: Make checksums for binaries (macOS) | |
if: runner.os == 'macOS' | |
shell: bash | |
run: | | |
for f in freelens/dist/Freelens*.*; do | |
shasum -a 256 "$f" | tee "$f.sha256" | |
done | |
- name: List files before upload | |
shell: bash | |
run: | | |
for f in freelens/dist/Freelens*.*; do | |
echo "$(ls -l "$f")" "|" "$(file -b "$f")" | |
done | |
- name: Upload files | |
if: github.ref_name == 'main' && github.event_name != 'pull_request' | |
shell: bash | |
run: | | |
gh release upload $tag \ | |
freelens/dist/Freelens*.* \ | |
--repo freelensapp/freelens-nightly-builds | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
tag: nightly-${{ needs.make-draft-release.outputs.date }} | |
outputs: | |
sha: ${{ steps.current_revision.outputs.sha }} | |
add-notes-to-release: | |
name: add notes to release | |
if: github.ref_name == 'main' && github.event_name != 'pull_request' | |
needs: | |
- make-draft-release | |
- build-app | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Add notes to nightly build | |
run: | | |
gh release edit nightly-${{ needs.make-draft-release.outputs.date }} \ | |
--notes="Based on https://github.com/freelensapp/freelens/commit/${{ needs.build-app.outputs.sha }}" | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
publish-release: | |
name: publish release | |
if: github.ref_name == 'main' && github.event_name != 'pull_request' | |
needs: | |
- make-draft-release | |
- build-app | |
- add-notes-to-release | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Publish nightly build | |
run: | | |
gh release edit $tag \ | |
--draft=false | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
tag: nightly-${{ needs.make-draft-release.outputs.date }} | |
- name: Delete old nightly builds | |
uses: nick-fields/retry@v3 | |
with: | |
timeout_minutes: 3 | |
max_attempts: 3 | |
retry_on: any | |
command: | | |
gh release list --json tagName --jq '.[].tagName' | \ | |
sort -r | \ | |
sed 1,10d | \ | |
xargs -IX -rn1 \ | |
gh release delete X --cleanup-tag --yes | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
release-apt-repository: | |
name: release APT repository | |
if: github.ref_name == 'main' && github.event_name != 'pull_request' | |
needs: | |
- make-draft-release | |
- publish-release | |
runs-on: ubuntu-24.04 | |
environment: apt-signing | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: GPG configuration | |
run: | | |
mkdir -p -m 0700 $HOME/.gnupg | |
echo "use-agent" > $HOME/.gnupg/gpg.conf | |
echo "pinentry-program $GITHUB_WORKSPACE/.github/scripts/pinentry.sh" > $HOME/.gnupg/gpg-agent.conf | |
echo "$GPG_PASSPHRASE" > $HOME/.gnupg/passphrase | |
gpgconf --launch gpg-agent | |
echo "$GPG_PRIVATE_KEY" | gpg --import | |
echo "$GPG_KEY_ID:6:" | gpg --import-ownertrust | |
env: | |
GPG_KEY_ID: ${{ vars.GPG_KEY_ID }} | |
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
- name: Release APT repository | |
run: | | |
set -x | |
gh release download $tag -p "*.deb" -D tmp | |
pushd tmp | |
apt-ftparchive packages . | tee Packages | xz > Packages.xz | |
apt-ftparchive release . > Release | |
gpg --clearsign -o InRelease Release | |
gpg --armor --detach-sign --sign -o Release.gpg Release | |
gh release upload $tag InRelease Packages Packages.xz Release Release.gpg --clobber | |
popd | |
env: | |
tag: nightly-${{ needs.make-draft-release.outputs.date }} | |
GH_TOKEN: ${{ secrets.GH_TOKEN }} |