Skip to content

feat: add homebrew cask release action #56

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,5 @@ jobs:
uses: ./.github/actions/nix-devshell

- run: make lint
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37 changes: 34 additions & 3 deletions .github/workflows/release.yml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: since we're gonna do preview builds off main we should probably call this build.yml & name: build.

Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
name: release

on:
push:
branches:
- main
release:
types: [published]

permissions: {}

jobs:
build:
name: Build Coder Desktop
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest'}}
if: ${{ github.repository_owner == 'coder' }}
permissions:
Expand Down Expand Up @@ -40,7 +44,34 @@ jobs:
run: make release

- name: Upload Release Assets
run: gh release upload "$RELEASE_TAG" "$out"/*
run: gh release upload "$RELEASE_TAG" "$out"/* --clobber
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event_name == 'release' && github.event.release.tag_name || 'preview' }}

update-cask:
name: Update homebrew-coder cask
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest'}}
if: ${{ github.repository_owner == 'coder' }}
needs: build
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 1
persist-credentials: false

- name: Setup Nix
uses: ./.github/actions/nix-devshell

- name: Update homebrew-coder
env:
GH_TOKEN: ${{ secrets.CODERCI_GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event_name == 'release' && github.event.release.tag_name || 'preview' }}
ASSIGNEE: ${{ github.actor }}
run: |
git config --global user.email "ci@coder.com"
git config --global user.name "Coder CI"
gh auth setup-git

./scripts/update-cask.sh --version "$RELEASE_TAG" --assignee "$ASSIGNEE"
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ XCPROJECT := Coder\ Desktop/Coder\ Desktop.xcodeproj
SCHEME := Coder\ Desktop
SWIFT_VERSION := 6.0

CURRENT_PROJECT_VERSION=$(shell git describe --tags)
CURRENT_PROJECT_VERSION:=$(shell git describe --match 'v[0-9]*' --dirty='.devel' --always --tags)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to look this up but = is lazy, := is eager - do we need eager here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more about not reevaluating the value assignment.
A simple = will result in continuous re-expansions of the variable.
A :=, on the other hand, will only be expanded once and then used as a "constant".

(https://www.gnu.org/software/make/manual/html_node/Simple-Assignment.html)

ifeq ($(strip $(CURRENT_PROJECT_VERSION)),)
$(error CURRENT_PROJECT_VERSION cannot be empty)
endif

MARKETING_VERSION=$(shell git describe --tags --abbrev=0 | sed 's/^v//' | sed 's/-.*$$//')
MARKETING_VERSION:=$(shell git describe --match 'v[0-9]*' --tags --abbrev=0 | sed 's/^v//' | sed 's/-.*$$//')
ifeq ($(strip $(MARKETING_VERSION)),)
$(error MARKETING_VERSION cannot be empty)
endif
Expand Down Expand Up @@ -132,3 +132,5 @@ help: ## Show this help
.PHONY: watch-gen
watch-gen: ## Generate Xcode project file and watch for changes
watchexec -w 'Coder Desktop/project.yml' make $(XCPROJECT)

print-%: ; @echo $*=$($*)
123 changes: 123 additions & 0 deletions scripts/update-cask.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#!/usr/bin/env bash
set -euo pipefail

usage() {
echo "Usage: $0 [--version <version>] [--assignee <github handle>]"
echo " --version <version> Set the VERSION variable to fetch and generate the cask file for"
echo " --assignee <github handle> Set the ASSIGNE variable to assign the PR to (optional)"
echo " -h, --help Display this help message"
}

VERSION=""
ASSIGNE=""

# Parse command line arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
--version)
VERSION="$2"
shift 2
;;
--assignee)
ASSIGNE="$2"
shift 2
;;
-h | --help)
usage
exit 0
;;
*)
echo "Unknown parameter passed: $1"
usage
exit 1
;;
esac
done

# Assert version is not empty and starts with v
[ -z "$VERSION" ] && {
echo "Error: VERSION cannot be empty"
exit 1
}
[[ "$VERSION" =~ ^v || "$VERSION" == "preview" ]] || {
echo "Error: VERSION must start with a 'v'"
exit 1
}

# Download the Coder Desktop dmg
GH_RELEASE_FOLDER=$(mktemp -d)

gh release download "$VERSION" \
--repo coder/coder-desktop-macos \
--dir "$GH_RELEASE_FOLDER" \
--pattern 'Coder.Desktop.dmg'

HASH=$(shasum -a 256 "$GH_RELEASE_FOLDER"/Coder.Desktop.dmg | awk '{print $1}' | tr -d '\n')

IS_PREVIEW=false
if [[ "$VERSION" == "preview" ]]; then
IS_PREVIEW=true
VERSION=$(make 'print-CURRENT_PROJECT_VERSION' | sed 's/CURRENT_PROJECT_VERSION=//g')
fi

# Check out the homebrew tap repo
TAP_CHECHOUT_FOLDER=$(mktemp -d)

gh repo clone "coder/homebrew-coder" "$TAP_CHECHOUT_FOLDER"

cd "$TAP_CHECHOUT_FOLDER"

BREW_BRANCH="auto-release/desktop-$VERSION"

# Check if a PR already exists.
# Continue on a main branch release, as the sha256 will change.
pr_count="$(gh pr list --search "head:$BREW_BRANCH" --json id,closed | jq -r ".[] | select(.closed == false) | .id" | wc -l)"
if [[ "$pr_count" -gt 0 && "$IS_PREVIEW" == false ]]; then
echo "Bailing out as PR already exists" 2>&1
exit 0
fi

git checkout -b "$BREW_BRANCH"

# If this is a main branch build, append a preview suffix to the cask.
SUFFIX=""
CONFLICTS_WITH="coder-desktop-preview"
TAG=$VERSION
if [[ "$IS_PREVIEW" == true ]]; then
SUFFIX="-preview"
CONFLICTS_WITH="coder-desktop"
TAG="preview"
fi

mkdir -p "$TAP_CHECHOUT_FOLDER"/Casks

# Overwrite the cask file
cat >"$TAP_CHECHOUT_FOLDER"/Casks/coder-desktop${SUFFIX}.rb <<EOF
cask "coder-desktop${SUFFIX}" do
version "${VERSION#v}"
sha256 "${HASH}"

url "https://github.com/coder/coder-desktop-macos/releases/download/${TAG}/Coder.Desktop.dmg"
name "Coder Desktop"
desc "Coder Desktop client"
homepage "https://github.com/coder/coder-desktop-macos"

depends_on macos: ">= :sonoma"

app "Coder Desktop.app"
conflicts_with cask: "coder/coder/${CONFLICTS_WITH}"
end
EOF

git add .
git commit -m "Coder Desktop $VERSION"
git push -u origin -f "$BREW_BRANCH"

# Create a PR only if none exists
if [[ "$pr_count" -eq 0 ]]; then
gh pr create \
--base master --head "$BREW_BRANCH" \
--title "Coder Desktop $VERSION" \
--body "This automatic PR was triggered by the release of Coder Desktop $VERSION" \
${ASSIGNE:+ --assignee "$ASSIGNE" --reviewer "$ASSIGNE"}
fi
Loading