Skip to content

20.2.0-rc.1

20.2.0-rc.1 #46

Workflow file for this run

name: Publish Package to npmjs
on:
release:
types: [published]
permissions:
actions: read
id-token: write
contents: write
jobs:
build-and-publish:
runs-on: ubuntu-latest
env:
# Bun 1.3.12 has a sig_size calculation bug in macho.zig that truncates the
# LC_CODE_SIGNATURE blob on cross-compiled Darwin binaries, so macOS kills
# them on launch (oven-sh/bun#29120). Unpin once a Bun release includes the
# upstream fix (oven-sh/bun#29122).
CLI_BUN_VERSION: '1.3.11'
HOMEBREW_TAP_REPO: appwrite/homebrew-appwrite
WINDOWS_SIGNING_PROJECT_SLUG: ${{ vars.WINDOWS_SIGNING_PROJECT_SLUG || 'sdk-for-cli' }}
WINDOWS_SIGNING_POLICY_SLUG: ${{ vars.WINDOWS_SIGNING_POLICY_SLUG || 'release-signing' }}
WINDOWS_SIGNING_ARTIFACT_CONFIGURATION_SLUG: ${{ vars.WINDOWS_SIGNING_ARTIFACT_CONFIGURATION_SLUG || 'initial' }}
steps:
- uses: actions/checkout@v6
with:
token: ${{ secrets.GH_TOKEN }}
- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.CLI_BUN_VERSION }}
- name: Setup binfmt with QEMU
run: |
sudo apt update
sudo apt install qemu-system binfmt-support qemu-user-static osslsigncode
update-binfmts --display
- name: Setup ldid
run: |
git clone https://github.com/tpoechtrager/ldid
cd ./ldid
sudo make
sudo make install
- name: Install dependencies and build for Linux and Windows
run: |
bun install --frozen-lockfile
bun run linux-x64
bun run linux-arm64
bun run mac-x64
bun run mac-arm64
bun run windows-x64
bun run windows-arm64
- name: Upload unsigned Windows binaries
id: upload-windows-unsigned
uses: actions/upload-artifact@v4
with:
name: windows-unsigned
path: |
build/appwrite-cli-win-x64.exe
build/appwrite-cli-win-arm64.exe
- name: Submit Windows binaries for signing
uses: signpath/github-action-submit-signing-request@b9d91eadd323de506c0c81cf0c7fe7438f3360fd # v2
with:
api-token: ${{ secrets.WINDOWS_SIGNING_API_TOKEN }}
organization-id: ${{ vars.WINDOWS_SIGNING_ORGANIZATION_ID }}
project-slug: ${{ env.WINDOWS_SIGNING_PROJECT_SLUG }}
signing-policy-slug: ${{ env.WINDOWS_SIGNING_POLICY_SLUG }}
artifact-configuration-slug: ${{ env.WINDOWS_SIGNING_ARTIFACT_CONFIGURATION_SLUG }}
github-artifact-id: ${{ steps.upload-windows-unsigned.outputs.artifact-id }}
wait-for-completion: true
output-artifact-directory: build-signed
parameters: |
version: "${{ github.event.release.tag_name }}"
- name: Replace unsigned Windows binaries
run: |
set -euo pipefail
signed_x64="$(find build-signed -type f -name 'appwrite-cli-win-x64.exe' -print -quit)"
signed_arm64="$(find build-signed -type f -name 'appwrite-cli-win-arm64.exe' -print -quit)"
if [ -z "$signed_x64" ] || [ -z "$signed_arm64" ]; then
echo "Signed Windows binaries were not found in build-signed"
find build-signed -type f -print
exit 1
fi
cp "$signed_x64" build/appwrite-cli-win-x64.exe
cp "$signed_arm64" build/appwrite-cli-win-arm64.exe
- name: Verify Windows signatures
run: |
set -uo pipefail
verify_signature() {
local file="$1"
local output rc
output="$(osslsigncode verify -in "$file" 2>&1)"
rc=$?
echo "--- $file (osslsigncode exit $rc) ---"
echo "$output"
if [ "$rc" -ne 0 ] || ! grep -Fq "Succeeded" <<< "$output"; then
echo "::error::$file signature verification failed"
return 1
fi
}
final=0
verify_signature build/appwrite-cli-win-x64.exe || final=1
verify_signature build/appwrite-cli-win-arm64.exe || final=1
exit "$final"
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '24.14.1'
registry-url: 'https://registry.npmjs.org'
- name: Pin npm for trusted publishing
run: npm install -g npm@11.10.0
- name: Determine release tag
id: release_tag
run: |
if [[ "${{ github.ref }}" == *"-rc"* ]] || [[ "${{ github.ref }}" == *"-RC"* ]]; then
echo "tag=next" >> "$GITHUB_OUTPUT"
else
echo "tag=latest" >> "$GITHUB_OUTPUT"
fi
- name: Publish
run: npm publish --provenance --access public --tag ${{ steps.release_tag.outputs.tag }}
- uses: fnkr/github-action-ghr@v1
env:
GHR_PATH: build/
GHR_REPLACE: false
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
- name: Check out Homebrew tap
uses: actions/checkout@v6
with:
repository: ${{ env.HOMEBREW_TAP_REPO }}
token: ${{ secrets.HOMEBREW_TAP_GH_TOKEN }}
path: homebrew-tap
fetch-depth: 0
- name: Update Homebrew formula in tap
id: tap
working-directory: homebrew-tap
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
set -euo pipefail
FORMULA_PATH="$(find Formula -maxdepth 1 -name '*.rb' | head -n 1)"
if [ -z "$FORMULA_PATH" ]; then
echo "No formula found in Homebrew tap"
exit 1
fi
EXECUTABLE_NAME="$(basename "$FORMULA_PATH" .rb)"
export FORMULA_PATH EXECUTABLE_NAME
export MAC_ARM64_SHA256="$(sha256sum "../build/${EXECUTABLE_NAME}-cli-darwin-arm64" | awk '{print $1}')"
export MAC_X64_SHA256="$(sha256sum "../build/${EXECUTABLE_NAME}-cli-darwin-x64" | awk '{print $1}')"
export LINUX_ARM64_SHA256="$(sha256sum "../build/${EXECUTABLE_NAME}-cli-linux-arm64" | awk '{print $1}')"
export LINUX_X64_SHA256="$(sha256sum "../build/${EXECUTABLE_NAME}-cli-linux-x64" | awk '{print $1}')"
ruby <<'RUBY'
formula_path = ENV.fetch("FORMULA_PATH")
executable = ENV.fetch("EXECUTABLE_NAME")
release_tag = ENV.fetch("RELEASE_TAG")
checksums = {
"#{executable}-cli-darwin-arm64" => ENV.fetch("MAC_ARM64_SHA256"),
"#{executable}-cli-darwin-x64" => ENV.fetch("MAC_X64_SHA256"),
"#{executable}-cli-linux-arm64" => ENV.fetch("LINUX_ARM64_SHA256"),
"#{executable}-cli-linux-x64" => ENV.fetch("LINUX_X64_SHA256"),
}
text = File.read(formula_path)
unless text.sub!(/^(\s*version ")([^"]+)(")$/) { "#{$1}#{release_tag}#{$3}" }
abort("Failed to update formula version")
end
checksums.each do |artifact, checksum|
pattern = /(#{Regexp.escape(artifact)}"\n\s+sha256 ")([0-9a-f]{64})(")/
unless text.sub!(pattern) { "#{$1}#{checksum}#{$3}" }
abort("Failed to update checksum for #{artifact}")
end
end
File.write(formula_path, text)
RUBY
ruby -c "$FORMULA_PATH"
{
echo "executable=${EXECUTABLE_NAME}"
echo "formula_path=${FORMULA_PATH}"
} >> "$GITHUB_OUTPUT"
- name: Open pull request on Homebrew tap
working-directory: homebrew-tap
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
EXECUTABLE_NAME: ${{ steps.tap.outputs.executable }}
FORMULA_PATH: ${{ steps.tap.outputs.formula_path }}
SOURCE_REPO: ${{ github.repository }}
SERVER_URL: ${{ github.server_url }}
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_GH_TOKEN }}
run: |
set -euo pipefail
if git diff --quiet -- "$FORMULA_PATH"; then
echo "Homebrew formula already up to date for ${RELEASE_TAG}"
exit 0
fi
BASE_BRANCH="$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name')"
BRANCH="release/${EXECUTABLE_NAME}-${RELEASE_TAG}"
git config user.name "appwrite-bot"
git config user.email "bot@appwrite.io"
git checkout -B "$BRANCH"
git add "$FORMULA_PATH"
git commit -m "${EXECUTABLE_NAME} ${RELEASE_TAG}"
git push -f -u origin "$BRANCH"
PR_TITLE="${EXECUTABLE_NAME} ${RELEASE_TAG}"
PR_BODY=$(printf 'Automated formula update for the `%s` CLI release [`%s`](%s/%s/releases/tag/%s).\n\nOpened automatically by the `%s` publish workflow after release binaries were uploaded.' "$EXECUTABLE_NAME" "$RELEASE_TAG" "$SERVER_URL" "$SOURCE_REPO" "$RELEASE_TAG" "${SOURCE_REPO#*/}")
EXISTING_PR="$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number' || true)"
if [ -n "$EXISTING_PR" ]; then
gh pr edit "$EXISTING_PR" --title "$PR_TITLE" --body "$PR_BODY"
else
gh pr create \
--title "$PR_TITLE" \
--body "$PR_BODY" \
--base "$BASE_BRANCH" \
--head "$BRANCH"
fi