Conversation
WalkthroughAdds a new release automation script for the desktop app, bumps the desktop package version, updates the GitHub Actions release workflow to separate artifact uploads and create stable copies, and disables auto-publish in the Electron Builder config; plus a minor test formatting tweak. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Script as create-release.sh
participant Local as Local Repo / Git
participant GHAPI as GitHub API
participant GHA as GitHub Actions
Note over Script: Release automation flow
User->>Script: run create-release.sh
Script->>Script: validate gh, auth, clean tree, repo root
Script->>Local: read & bump apps/desktop/package.json
Script->>Local: git add/commit & push branch
Script->>Local: create & push tag (desktop-v*)
Script->>GHA: poll workflow run for tag (retry/backoff)
GHA-->>Script: workflow run status
Script->>GHAPI: poll for draft release (retry)
GHAPI-->>Script: draft release URL & assets
Script->>GHAPI: publish draft release (when ready)
Script->>User: print release URL and artifact paths
sequenceDiagram
autonumber
participant Builder as Build job
participant Upload as Upload artifacts
participant Download as Download artifacts step
participant Post as Post-download processing
participant Release as Create GitHub Release
Note over Upload: artifacts uploaded separately (DMG, ZIP)
Builder->>Upload: upload DMG artifacts (desktop-mac-*-dmg)
Builder->>Upload: upload ZIP artifacts (desktop-mac-*-zip)
Download->>Upload: download with merge-multiple:true
Download->>Post: provide downloaded files
Post->>Post: create stable copies (Superset-${arch}.dmg, Superset-${arch}-mac.zip)
Post->>Release: attach `release-artifacts/*` to release
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings, 1 inconclusive)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…e-release script - Add GitHub CLI validation and authentication checks - Monitor GitHub Actions workflow in real-time - Display draft release URL when ready - Add retry logic for workflow and release detection - Improve error handling and user feedback
npm version doesn't work with workspace dependencies, so use jq instead to directly modify the version field.
The CI/CD pipeline handles the build, so building locally is unnecessary and can cause issues with notarization credentials.
There was a problem hiding this comment.
Actionable comments posted: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/desktop/create-release.sh(1 hunks)apps/desktop/package.json(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Biome formatting, linting, and import organization at the root level for all code files
Files:
apps/desktop/package.json
🧠 Learnings (1)
📚 Learning: 2025-11-24T21:32:46.559Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T21:32:46.559Z
Learning: Applies to apps/desktop/electron.vite.config.ts : Load environment variables in electron.vite.config.ts with override: true for build-time configuration
Applied to files:
apps/desktop/package.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build
- GitHub Check: Build - macOS (arm64)
🔇 Additional comments (4)
apps/desktop/create-release.sh (3)
77-77: Verify git operations work correctly from desktop subdirectory.After changing to the
apps/desktopdirectory on line 77, all subsequentgitcommands operate from that subdirectory. While Git handles subdirectory operations correctly, ensure that:
- Remote references and branch/tag operations target the monorepo root correctly
- The
REPOextraction on line 132 (executed after thecd) uses the correct working directory- Push operations (lines 113, 122) push to the correct origin
Verify that git operations work as expected by running the script in a test environment or adding debug output. Alternatively, consider storing the repository information and tag operations before changing directories, or restoring the working directory at key points.
1-223: Excellent script structure and documentation.The overall script design is solid: clear documentation header, good modular helper functions, sensible prerequisite checks, and logical flow. The use of colors, retry logic, and user-friendly messages enhances the UX. Beyond the specific issues flagged above (workflow filter bug and error handling), the script is well-architected.
4-4: The referencedapps/desktop/RELEASE.mdfile exists and contains current release documentation.The file contains 154 lines of substantive release process documentation, including prerequisites and multiple release methods. The comment on line 4 of
create-release.shcorrectly references this existing documentation.apps/desktop/package.json (1)
5-5: Version bump from 0.0.0 to 0.0.1 is correct and file is valid JSON.The version change aligns with release expectations. The
package.jsonfile is properly formatted with valid JSON syntax and consistent 2-space indentation. The file includes Biome as a dev dependency (v2.2.6), and the formatting is compliant with standard JSON conventions.
|
|
||
| # Check if version argument is provided | ||
| if [ -z "$1" ]; then | ||
| error "Usage: $0 <version>\nExample: $0 0.0.1" |
There was a problem hiding this comment.
Fix error message formatting.
The error message uses \n but the error() function (line 44–47) doesn't use the -e flag with echo, so escape sequences won't be interpreted. The newline won't render.
Apply this diff:
- error "Usage: $0 <version>\nExample: $0 0.0.1"
+ error "Usage: $0 <version>"
+ error "Example: $0 0.0.1"Alternatively, update the error() function to use echo -e:
error() {
- echo -e "${RED}✗${NC} $1"
+ echo -e "${RED}✗${NC} $1" >&2
exit 1
}(The >&2 redirection is also recommended for error output.)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| error "Usage: $0 <version>\nExample: $0 0.0.1" | |
| error "Usage: $0 <version>" | |
| error "Example: $0 0.0.1" |
🤖 Prompt for AI Agents
In apps/desktop/create-release.sh around line 51, the error message uses "\n"
but the error() helper doesn't pass -e to echo so escapes won't be interpreted;
update the error() function (lines ~44–47) to use echo -e and redirect output to
stderr (e.g., echo -e "msg" >&2) or change the specific call at line 51 to
invoke echo -e >&2 so the newline renders and the message is sent to stderr.
| TMP_FILE=$(mktemp) | ||
| jq ".version = \"${VERSION}\"" package.json > "${TMP_FILE}" && mv "${TMP_FILE}" package.json |
There was a problem hiding this comment.
Add error handling for jq operations.
The temporary file and jq pipeline on lines 100–101 lack error handling. If jq fails or the file move is interrupted, the script continues with corrupted state.
Apply this diff to add proper error handling:
- TMP_FILE=$(mktemp)
- jq ".version = \"${VERSION}\"" package.json > "${TMP_FILE}" && mv "${TMP_FILE}" package.json
+ TMP_FILE=$(mktemp) || error "Failed to create temporary file"
+ if jq ".version = \"${VERSION}\"" package.json > "${TMP_FILE}"; then
+ mv "${TMP_FILE}" package.json || error "Failed to move updated package.json"
+ else
+ rm -f "${TMP_FILE}"
+ error "Failed to update package.json version"
+ fiThis ensures cleanup and explicit error messages if any step fails.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/desktop/create-release.sh around lines 100–101, the TMP_FILE creation,
jq write and mv lack error handling; create TMP_FILE and immediately test its
success, add a trap to remove TMP_FILE on EXIT, run jq writing to TMP_FILE and
check jq's exit status before proceeding, on jq failure delete TMP_FILE and exit
with an error, only run mv if jq succeeded and check mv's exit status (on
failure delete TMP_FILE and exit with an error), and emit clear error messages
for each failure so the script cannot continue with a corrupted package.json.
| # 6. Monitor the workflow | ||
| info "Monitoring GitHub Actions workflow..." | ||
| echo " Waiting for workflow to start (this may take a few seconds)..." | ||
|
|
||
| # Wait and retry to find the workflow run | ||
| MAX_RETRIES=6 | ||
| RETRY_COUNT=0 | ||
| WORKFLOW_RUN="" | ||
|
|
||
| while [ $RETRY_COUNT -lt $MAX_RETRIES ] && [ -z "$WORKFLOW_RUN" ]; do | ||
| sleep 5 | ||
| WORKFLOW_RUN=$(gh run list --workflow=release-desktop.yml --json databaseId,headBranch,status --jq ".[] | select(.headBranch == \"${TAG_NAME}\") | .databaseId" | head -1) | ||
| RETRY_COUNT=$((RETRY_COUNT + 1)) | ||
|
|
||
| if [ -z "$WORKFLOW_RUN" ] && [ $RETRY_COUNT -lt $MAX_RETRIES ]; then | ||
| echo " Still waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)" | ||
| fi | ||
| done | ||
|
|
||
| if [ -z "$WORKFLOW_RUN" ]; then | ||
| warn "Could not find workflow run automatically" | ||
| echo " Manual monitoring URL:" | ||
| echo " https://github.com/${REPO}/actions" | ||
| echo "" | ||
| warn "The workflow may still be starting. Check the URL above in a few moments." | ||
| else | ||
| success "Found workflow run: ${WORKFLOW_RUN}" | ||
| echo "" | ||
| info "Watching workflow progress..." | ||
| echo " View in browser: https://github.com/${REPO}/actions/runs/${WORKFLOW_RUN}" | ||
| echo "" | ||
|
|
||
| # Watch the workflow (this will stream the status) | ||
| gh run watch "${WORKFLOW_RUN}" || warn "Workflow monitoring interrupted" | ||
|
|
||
| # Check final status | ||
| WORKFLOW_STATUS=$(gh run view "${WORKFLOW_RUN}" --json conclusion --jq .conclusion) | ||
|
|
||
| if [ "$WORKFLOW_STATUS" == "success" ]; then | ||
| success "Workflow completed successfully!" | ||
| elif [ "$WORKFLOW_STATUS" == "failure" ]; then | ||
| error "Workflow failed. Please check the logs at: https://github.com/${REPO}/actions/runs/${WORKFLOW_RUN}" | ||
| else | ||
| warn "Workflow ended with status: ${WORKFLOW_STATUS}" | ||
| fi | ||
| fi |
There was a problem hiding this comment.
Workflow monitoring cascades into false-negative state due to filter bug.
Because the workflow detection on line 145 uses an incorrect filter (as noted in the critical issue above), the monitoring section (lines 134–179) will always enter the else branch at line 153, displaying a warning that "Could not find workflow run automatically" and directing users to manual monitoring. This masks the underlying filter bug and degrades user experience.
Once the filter bug on line 145 is fixed, this section should work correctly.
🤖 Prompt for AI Agents
In apps/desktop/create-release.sh around lines 134 to 179, the workflow
detection fails because the jq filter only checks .headBranch, which is null for
tag-triggered runs; change the WORKFLOW_RUN assignment so the jq select matches
either .headBranch or .headRef (the tag ref) — e.g. use a predicate like
select((.headBranch == "${TAG_NAME}") or (.headRef == "${TAG_NAME}")) — so
tagged releases are found and the monitoring branch works as intended.
|
|
||
| while [ $RETRY_COUNT -lt $MAX_RETRIES ] && [ -z "$WORKFLOW_RUN" ]; do | ||
| sleep 5 | ||
| WORKFLOW_RUN=$(gh run list --workflow=release-desktop.yml --json databaseId,headBranch,status --jq ".[] | select(.headBranch == \"${TAG_NAME}\") | .databaseId" | head -1) |
There was a problem hiding this comment.
🧩 Analysis chain
Script executed:
#!/bin/bash
# Inspect the create-release.sh script around line 145
sed -n '130,160p' apps/desktop/create-release.shRepository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
stdout:
# Get repository information
REPO=$(git remote get-url origin | sed 's/.*github.com[:/]\(.*\)\.git/\1/')
# 6. Monitor the workflow
info "Monitoring GitHub Actions workflow..."
echo " Waiting for workflow to start (this may take a few seconds)..."
# Wait and retry to find the workflow run
MAX_RETRIES=6
RETRY_COUNT=0
WORKFLOW_RUN=""
while [ $RETRY_COUNT -lt $MAX_RETRIES ] && [ -z "$WORKFLOW_RUN" ]; do
sleep 5
WORKFLOW_RUN=$(gh run list --workflow=release-desktop.yml --json databaseId,headBranch,status --jq ".[] | select(.headBranch == \"${TAG_NAME}\") | .databaseId" | head -1)
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ -z "$WORKFLOW_RUN" ] && [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
echo " Still waiting... (attempt $RETRY_COUNT/$MAX_RETRIES)"
fi
done
if [ -z "$WORKFLOW_RUN" ]; then
warn "Could not find workflow run automatically"
echo " Manual monitoring URL:"
echo " https://github.com/${REPO}/actions"
echo ""
warn "The workflow may still be starting. Check the URL above in a few moments."
else
success "Found workflow run: ${WORKFLOW_RUN}"
</shell_result>
Script executed:
#!/bin/bash
# Also check the beginning of the script to see TAG_NAME derivation
sed -n '1,100p' apps/desktop/create-release.sh | head -80Repository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
stdout:
#!/usr/bin/env bash
# Desktop App Release Script
# Based on apps/desktop/RELEASE.md
#
# Usage:
# ./create-release.sh <version>
# Example: ./create-release.sh 0.0.1
#
# This script will:
# 1. Verify prerequisites (clean git, GitHub CLI authenticated)
# 2. Update package.json version
# 3. Create and push a git tag to trigger the release workflow
# 4. Monitor the GitHub Actions workflow in real-time
# 5. Display the draft release URL when ready
#
# Requirements:
# - GitHub CLI (gh) installed and authenticated
# - Clean working directory
# - Running from monorepo root
set -e # Exit on error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions
info() {
echo -e "${BLUE}ℹ ${NC}$1"
}
success() {
echo -e "${GREEN}✓${NC} $1"
}
warn() {
echo -e "${YELLOW}⚠${NC} $1"
}
error() {
echo -e "${RED}✗${NC} $1"
exit 1
}
# Check if version argument is provided
if [ -z "$1" ]; then
error "Usage: $0 <version>\nExample: $0 0.0.1"
fi
VERSION="$1"
TAG_NAME="desktop-v${VERSION}"
DESKTOP_DIR="apps/desktop"
# Check if gh CLI is installed
if ! command -v gh &> /dev/null; then
error "GitHub CLI (gh) is required but not installed.\nInstall it from: https://cli.github.com/"
fi
# Check if authenticated with gh
if ! gh auth status &> /dev/null; then
error "Not authenticated with GitHub CLI.\nRun: gh auth login"
fi
info "Starting release process for version ${VERSION}"
echo ""
# Check if we're in the monorepo root
if [ ! -f "package.json" ] || [ ! -d "apps/desktop" ]; then
error "Please run this script from the monorepo root directory"
fi
# Navigate to desktop app directory
cd "${DESKTOP_DIR}"
# 1. Check for uncommitted changes
info "Checking for uncommitted changes..."
</shell_result>
Script executed:
#!/bin/bash
# Find where TAG_NAME is used, particularly the git push command
sed -n '100,130p' apps/desktop/create-release.shRepository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
stdout:
TMP_FILE=$(mktemp)
jq ".version = \"${VERSION}\"" package.json > "${TMP_FILE}" && mv "${TMP_FILE}" package.json
success "Updated package.json from ${CURRENT_VERSION} to ${VERSION}"
# Commit the version change
git add package.json
git commit -m "chore(desktop): bump version to ${VERSION}"
success "Committed version change"
fi
# 4. Push changes
info "Pushing changes to remote..."
CURRENT_BRANCH=$(git branch --show-current)
git push origin "${CURRENT_BRANCH}"
success "Changes pushed to ${CURRENT_BRANCH}"
# 5. Create and push tag
info "Creating tag ${TAG_NAME}..."
git tag "${TAG_NAME}"
success "Tag ${TAG_NAME} created"
info "Pushing tag to trigger release workflow..."
git push origin "${TAG_NAME}"
success "Tag pushed to remote"
echo ""
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}🎉 Release process initiated successfully!${NC}"
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
</shell_result>
Script executed:
#!/bin/bash
# Search for the entire tag push section
sed -n '116,125p' apps/desktop/create-release.shRepository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
stdout:
# 5. Create and push tag
info "Creating tag ${TAG_NAME}..."
git tag "${TAG_NAME}"
success "Tag ${TAG_NAME} created"
info "Pushing tag to trigger release workflow..."
git push origin "${TAG_NAME}"
success "Tag pushed to remote"
echo ""
</shell_result>
Script executed:
#!/bin/bash
# Get the git operations and tag push
sed -n '110,135p' apps/desktop/create-release.shRepository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
stdout:
# 4. Push changes
info "Pushing changes to remote..."
CURRENT_BRANCH=$(git branch --show-current)
git push origin "${CURRENT_BRANCH}"
success "Changes pushed to ${CURRENT_BRANCH}"
# 5. Create and push tag
info "Creating tag ${TAG_NAME}..."
git tag "${TAG_NAME}"
success "Tag ${TAG_NAME} created"
info "Pushing tag to trigger release workflow..."
git push origin "${TAG_NAME}"
success "Tag pushed to remote"
echo ""
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}🎉 Release process initiated successfully!${NC}"
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
# Get repository information
REPO=$(git remote get-url origin | sed 's/.*github.com[:/]\(.*\)\.git/\1/')
# 6. Monitor the workflow
info "Monitoring GitHub Actions workflow..."
</shell_result>
Script executed:
#!/bin/bash
# Query recent workflow runs to inspect the actual structure returned by gh
# This will show us what fields are available
gh run list --workflow=release-desktop.yml --json databaseId,headBranch,baseRef,headRef,headRefName,name,status,conclusion --limit 3Repository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 1
stderr:
Unknown JSON field: "baseRef"
Available fields:
attempt
conclusion
createdAt
databaseId
displayTitle
event
headBranch
headSha
name
number
startedAt
status
updatedAt
url
workflowDatabaseId
workflowName
</shell_result>
Script executed:
#!/bin/bash
# Also check the release-desktop.yml workflow file to understand the trigger
find . -name "release-desktop.yml" -type fRepository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
stdout:
./.github/workflows/release-desktop.yml
</shell_result>
Script executed:
#!/bin/bash
# Read the workflow file to see the trigger configuration
cat -n ./github/workflows/release-desktop.ymlRepository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 1
stderr:
cat: ./github/workflows/release-desktop.yml: No such file or directory
</shell_result>
Script executed:
#!/bin/bash
# Search for other gh run list usages in the codebase
rg "gh run list" --type bash -A 3 -B 3Repository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 2
stderr:
unrecognized file type: bash
</shell_result>
Script executed:
#!/bin/bash
# Check GitHub CLI documentation for tag-triggered workflow filtering
# Also check if there's any test or documentation about this
find . -type f -name "*.md" | xargs grep -l "gh run" 2>/dev/null | head -5Repository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
</shell_result>
Script executed:
#!/bin/bash
# Create a test to understand GitHub Actions API response for different trigger types
# Query the GitHub API documentation info (if available) or check gh help
gh run list --help | grep -A 20 "json"Repository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
stdout:
--json fields Output JSON with the specified fields
-L, --limit int Maximum number of runs to fetch (default 20)
-s, --status string Filter runs by status: {queued|completed|in_progress|requested|waiting|pending|action_required|cancelled|failure|neutral|skipped|stale|startup_failure|success|timed_out}
-t, --template string Format JSON output using a Go template; see "gh help formatting"
-u, --user string Filter runs by user who triggered the run
-w, --workflow string Filter runs by workflow
INHERITED FLAGS
--help Show help for command
-R, --repo [HOST/]OWNER/REPO Select another repository using the [HOST/]OWNER/REPO format
JSON FIELDS
attempt, conclusion, createdAt, databaseId, displayTitle, event, headBranch,
headSha, name, number, startedAt, status, updatedAt, url, workflowDatabaseId,
workflowName
LEARN MORE
Use `gh <command> <subcommand> --help` for more information about a command.
Read the manual at https://cli.github.com/manual
Learn about exit codes using `gh help exit-codes`
Learn about accessibility experiences using `gh help accessibility`
</shell_result>
Script executed:
#!/bin/bash
# Check if there's any RELEASE.md or documentation about the release process
cat -n apps/desktop/RELEASE.md 2>/dev/null | head -50Repository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
stdout:
1 # Desktop App Release Process
2
3 This document describes how to create a release for the Superset Desktop application.
4
5 ## Prerequisites
6
7 - Ensure all changes are committed and pushed to the repository
8 - Ensure the build works locally: `bun run package`
9 - Update version in `package.json` if needed
10
11 ## Release Methods
12
13 ### Method 1: Tag-Based Release (Recommended)
14
15 Create and push a git tag with the format `desktop-v*.*.*`:
16
17 ```bash
18 # Create a tag (e.g., desktop-v1.0.0)
19 git tag desktop-v1.0.0
20
21 # Push the tag to trigger the release workflow
22 git push origin desktop-v1.0.0
23 ```
24
25 This will automatically:
26 1. Build the app for macOS (arm64), Windows (x64), and Linux (x64)
27 2. Create artifacts for each platform
28 3. Create a draft GitHub release with all binaries attached
29
30 ### Method 2: Manual Workflow Dispatch
31
32 You can also trigger a release manually from GitHub Actions:
33
34 1. Go to Actions → Release Desktop App
35 2. Click "Run workflow"
36 3. Enter the version number (e.g., `1.0.0`)
37 4. Click "Run workflow"
38
39 This method is useful for testing the workflow or creating builds without creating a tag.
40
41 ## Workflow Overview
42
43 The release workflow (`.github/workflows/release-desktop.yml`) performs the following:
44
45 ### Build Platform
46
47 Builds are created for:
48 - **macOS**: arm64 (Apple Silicon) - produces `.dmg` and `.zip`
49
50 ### Build Steps
</shell_result>
Script executed:
#!/bin/bash
# Read the RELEASE.md file
cat -n apps/desktop/RELEASE.mdRepository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 0
stdout:
1 # Desktop App Release Process
2
3 This document describes how to create a release for the Superset Desktop application.
4
5 ## Prerequisites
6
7 - Ensure all changes are committed and pushed to the repository
8 - Ensure the build works locally: `bun run package`
9 - Update version in `package.json` if needed
10
11 ## Release Methods
12
13 ### Method 1: Tag-Based Release (Recommended)
14
15 Create and push a git tag with the format `desktop-v*.*.*`:
16
17 ```bash
18 # Create a tag (e.g., desktop-v1.0.0)
19 git tag desktop-v1.0.0
20
21 # Push the tag to trigger the release workflow
22 git push origin desktop-v1.0.0
23 ```
24
25 This will automatically:
26 1. Build the app for macOS (arm64), Windows (x64), and Linux (x64)
27 2. Create artifacts for each platform
28 3. Create a draft GitHub release with all binaries attached
29
30 ### Method 2: Manual Workflow Dispatch
31
32 You can also trigger a release manually from GitHub Actions:
33
34 1. Go to Actions → Release Desktop App
35 2. Click "Run workflow"
36 3. Enter the version number (e.g., `1.0.0`)
37 4. Click "Run workflow"
38
39 This method is useful for testing the workflow or creating builds without creating a tag.
40
41 ## Workflow Overview
42
43 The release workflow (`.github/workflows/release-desktop.yml`) performs the following:
44
45 ### Build Platform
46
47 Builds are created for:
48 - **macOS**: arm64 (Apple Silicon) - produces `.dmg` and `.zip`
49
50 ### Build Steps
51
52 1. Checkout code
53 2. Setup Bun
54 3. Install dependencies
55 4. Clean dev folder (`bun run clean:dev`)
56 5. Compile app with electron-vite (`bun run compile:app`)
57 6. Package with electron-builder (`bun run package`)
58 7. Upload artifacts
59
60 ### Release Creation
61
62 After the build completes (tag-based releases only):
63 1. Downloads all artifacts
64 2. Creates a draft GitHub release
65 3. Attaches all binaries to the release
66 4. Generates release notes from commits
67
68 ## Code Signing (Optional)
69
70 To enable macOS code signing, add the following secrets to your GitHub repository:
71
72 ```yaml
73 CSC_LINK: ${{ secrets.MAC_CERTIFICATE }}
74 CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTIFICATE_PASSWORD }}
75 APPLEID: ${{ secrets.APPLE_ID }}
76 APPLEIDPASS: ${{ secrets.APPLE_ID_PASSWORD }}
77 ```
78
79 Then uncomment the environment variables in the workflow under "Build Electron app".
80
81 ## Publishing the Release
82
83 1. After the workflow completes, go to GitHub Releases
84 2. Find the draft release
85 3. Review the release notes and binaries
86 4. Edit the release description if needed
87 5. Click "Publish release" to make it public
88
89 ## Build Outputs
90
91 ### macOS (arm64)
92 - `Superset-<version>-arm64.dmg` - DMG installer
93 - `Superset-<version>-arm64-mac.zip` - Zipped app bundle
94
95 ## Troubleshooting
96
97 ### Build fails on macOS
98
99 - Ensure you're building for the correct architecture (arm64 is configured by default)
100 - Check that icon files exist at `src/resources/build/icons/icon.icns`
101 - Verify that dependencies are properly installed
102
103 ### Native module errors
104
105 - `node-pty` is configured as a native module in both `electron.vite.config.ts` and `electron-builder.ts`
106 - It's externalized during build and unpacked from ASAR
107 - If you add more native modules, update both configuration files
108
109 ### Missing icons error
110
111 - The macOS build requires `icon.icns` in `src/resources/build/icons/`
112 - Ensure this file is committed to the repository
113
114 ## Local Testing
115
116 To test the build locally before releasing:
117
118 ```bash
119 cd apps/desktop
120
121 # Clean and compile
122 bun run clean:dev
123 bun run compile:app
124
125 # Package the app
126 bun run package
127 ```
128
129 The output will be in `apps/desktop/release/`.
130
131 ## Building for Intel Macs (x64)
132
133 To also build for Intel Macs, update `electron-builder.ts`:
134
135 ```typescript
136 mac: {
137 target: [
138 {
139 target: "default",
140 arch: ["arm64", "x64"], // Add x64 for Intel Macs
141 },
142 ],
143 }
144 ```
145
146 Note: This will increase build time significantly.
147
148 ## Adding Windows/Linux Builds
149
150 Currently only macOS builds are supported in CI/CD. To add Windows or Linux:
151
152 1. Add PNG icon files to `src/resources/build/icons/` (for Linux)
153 2. Update the workflow matrix in `.github/workflows/release-desktop.yml`
154 3. Update `electron-builder.ts` configuration as needed
</shell_result>
Script executed:
#!/bin/bash
# Search for any commented examples or documentation about headBranch
rg "headBranch|baseRef|headRef" --type bash -B 5 -A 5Repository: superset-sh/superset
<shell_result>
Repository: superset-sh/superset
Exit code: 2
stderr:
unrecognized file type: bash
</shell_result>
GitHub Actions API workflow run headBranch field tag push trigger
<web_search_result>
Short answer: when a workflow run is triggered by a push of a tag, the workflow-run/Actions API does not populate a branch name in head_branch — you should treat head_branch as null and use the run's ref/head_sha (or the push webhook's ref which will be refs/tags/) to detect the tag and its commit. [1][2][3]
Why / how to handle it
- A push event for a tag sets GITHUB_REF to refs/tags/ (not a refs/heads/... branch). Use that ref or the run's head_sha to identify the tag commit. [1]
- The Actions REST API / workflow-run responses expose head_branch (branch name) and head_sha (commit SHA); head_branch can be null (e.g., non-branch refs or certain fork/PR cases), so rely on head_sha + ref to tell tags apart. [2][3]
References
- Push & trigger behavior (ref is refs/tags/ for tag pushes). [1]
- Actions REST API / workflow run listing (head_branch / head_sha fields). [2]
- Community / API notes showing head_branch may be null (use head_sha/ref instead). [3]
</web_search_result>
GitHub Actions API headRefName field tag workflow runs
<web_search_result>
Short answer: headRefName (aka head_ref / github.head_ref) is only set for pull_request (and pull_request_target) runs — it will be null/empty for tag (push tag / release) workflow runs. For tag-triggered runs use the run's ref/ref_name or head_sha instead.
Sources:
- GitHub Actions contexts: github.head_ref only available for pull_request / pull_request_target; github.ref and github.ref_name show branch or tag refs. [1]
- REST API workflow-runs docs: list/get workflow run responses do not populate a pull-request head_ref for push/tag events; use ref/head_sha to identify the trigger. [2]
References:
[1] https://docs.github.com/en/actions/using-workflows/contexts-and-expression-syntax-for-github-actions#github-context
[2] https://docs.github.com/en/rest/actions/workflow-runs (List/Get workflow runs)
</web_search_result>
Workflow detection filter is incompatible with tag-triggered runs.
Line 145 filters by headBranch == "${TAG_NAME}", but GitHub Actions does not populate headBranch for workflows triggered by tag pushes—it returns null or the underlying branch (e.g., "main"), never the tag name. This filter will always fail, exhausting all retries and falling back to the manual monitoring warning.
Available fields in gh run list output are: attempt, conclusion, createdAt, databaseId, displayTitle, event, headBranch, headSha, name, number, startedAt, status, updatedAt, url, workflowDatabaseId, workflowName. Use event or headSha combined with commit metadata to identify the tag-triggered run, or query the workflow run details via a different mechanism.
Suggested investigation: query a recent run using gh run view <run-id> --json event,headBranch to confirm the actual API response for tag-triggered workflows, then adjust the filter accordingly.
🤖 Prompt for AI Agents
In apps/desktop/create-release.sh around line 145, the script filters workflow
runs by headBranch == "${TAG_NAME}", which fails for tag-triggered runs because
headBranch is not the tag; instead, resolve the tag's commit SHA (e.g.,
TAG_SHA=$(git rev-parse "${TAG_NAME}")) and use gh run list
--workflow=release-desktop.yml --json databaseId,event,headSha --jq '.[] |
select(.event=="push" and .headSha == "'"${TAG_SHA}"'") | .databaseId' to
reliably find the run for that tag (alternatively query runs and call gh run
view <id> --json event,headBranch to inspect responses before finalizing the
filter).
Split the single artifact upload into separate DMG and ZIP uploads to avoid the nested zip issue when downloading from GitHub Actions. Also use merge-multiple for cleaner artifact handling in releases. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Add stable-named copies of release assets (without version numbers) to enable GitHub's /releases/latest/download/ URL pattern. Users can now use stable URLs like: - https://github.com/.../releases/latest/download/Superset-arm64.dmg - https://github.com/.../releases/latest/download/Superset-arm64-mac.zip Versioned filenames are still available for users who need specific versions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/release-desktop.yml (1)
127-135: Based on my verification:
- v1 is genuinely deprecated: The
softprops/action-gh-release@v1uses the Node 12 runtime, which GitHub deprecated and enforced migration away from in 2023.- v2 is stable and current: The latest release is v2.4.2 (November 8, 2025), and the action's README recommends v2 in its usage examples.
- The warning will occur: Actions using v1 will trigger GitHub's "Node.js 12 actions are deprecated" warning in workflow logs.
- The upgrade is straightforward: The v2 release maintains backward compatibility with the configuration options used in the snippet (files, draft, generate_release_notes, name, env).
The original review comment's recommendation is accurate and should be preserved.
Update
softprops/action-gh-releaseto v2 or later.The
softprops/action-gh-release@v1action uses the Node 12 runtime, which GitHub deprecated and no longer supports on hosted runners. This will cause deprecation warnings and potential failures. The latest stable release (v2.4.2) uses a modern Node runtime and is fully backward-compatible with your current configuration.- name: Create Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: files: release-artifacts/* draft: true generate_release_notes: true name: Superset Desktop ${{ github.ref_name }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
♻️ Duplicate comments (2)
apps/desktop/create-release.sh (2)
142-157: Hardenjq/tempfile handling to avoid silent version bump failures.If
jqfails (syntax issue, missing binary, etc.), the&& mvis skipped but the script continues, leavingpackage.jsonunchanged while still printing a success message and potentially committing a misleading bump. The temporary file is also left behind.Consider something like:
- TMP_FILE=$(mktemp) - jq ".version = \"${VERSION}\"" package.json > "${TMP_FILE}" && mv "${TMP_FILE}" package.json - success "Updated package.json from ${CURRENT_VERSION} to ${VERSION}" + TMP_FILE=$(mktemp) || error "Failed to create temporary file" + if jq ".version = \"${VERSION}\"" package.json > "${TMP_FILE}"; then + mv "${TMP_FILE}" package.json || error "Failed to move updated package.json" + success "Updated package.json from ${CURRENT_VERSION} to ${VERSION}" + else + rm -f "${TMP_FILE}" + error "Failed to update package.json version" + fiThis guarantees either a correct version update or a clear, early failure.
187-228: Workflow run detection usingheadBranch == "${TAG_NAME}"will never match tag-triggered runs.
gh run list’sheadBranchis a branch name (or null) and does not equal the tag name for tag pushes, so theselect(.headBranch == "${TAG_NAME}")predicate will always fail for the release workflow. As a result, monitoring almost always falls back to the “manual monitoring” path even when the workflow is running, degrading the scripted UX and masking real failures.A more robust approach is to resolve the tag’s commit SHA and filter by that:
info "Monitoring GitHub Actions workflow..." echo " Waiting for workflow to start (this may take a few seconds)..." -# Wait and retry to find the workflow run -MAX_RETRIES=6 -RETRY_COUNT=0 -WORKFLOW_RUN="" - -while [ $RETRY_COUNT -lt $MAX_RETRIES ] && [ -z "$WORKFLOW_RUN" ]; do - sleep 5 - WORKFLOW_RUN=$(gh run list --workflow=release-desktop.yml --json databaseId,headBranch,status --jq ".[] | select(.headBranch == \"${TAG_NAME}\") | .databaseId" | head -1) - RETRY_COUNT=$((RETRY_COUNT + 1)) +TAG_SHA=$(git rev-parse "${TAG_NAME}") + +# Wait and retry to find the workflow run for this tag commit +MAX_RETRIES=6 +RETRY_COUNT=0 +WORKFLOW_RUN="" + +while [ $RETRY_COUNT -lt $MAX_RETRIES ] && [ -z "$WORKFLOW_RUN" ]; do + sleep 5 + WORKFLOW_RUN=$( + gh run list \ + --workflow=release-desktop.yml \ + --json databaseId,headSha,event,status \ + --jq ".[] | select(.event == \"push\" and .headSha == \"${TAG_SHA}\") | .databaseId" \ + | head -1 + ) + RETRY_COUNT=$((RETRY_COUNT + 1))Please confirm this matches how your release-desktop workflow is triggered (tag push vs other events) and adjust the
eventfilter if needed.
🧹 Nitpick comments (1)
apps/desktop/create-release.sh (1)
259-272: Align direct download URLs with the “stable copy” artifact naming.The workflow step creates stable, versionless copies (
Superset-${arch}.dmg,Superset-${arch}-mac.zip) specifically for/releases/latest/download/, but the script prints versioned filenames in those URLs. The current links will work, but they don’t take advantage of the stable names.Either point at the stable assets:
- echo " • ${LATEST_URL}/download/Superset-${VERSION}-arm64.dmg" - echo " • ${LATEST_URL}/download/Superset-${VERSION}-arm64-mac.zip" + echo " • ${LATEST_URL}/download/Superset-arm64.dmg" + echo " • ${LATEST_URL}/download/Superset-arm64-mac.zip"or update the workflow comments if you prefer the versioned filenames as the canonical download targets.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.github/workflows/release-desktop.yml(3 hunks)apps/desktop/create-release.sh(1 hunks)apps/desktop/electron-builder.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Biome formatting, linting, and import organization at the root level for all code files
Files:
apps/desktop/electron-builder.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Avoid usinganytype; use type-safe approaches instead, unless necessary
Ensure TypeScript type checking passes across all packages using bun run typecheck
Files:
apps/desktop/electron-builder.ts
apps/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/**/*.{tsx,ts}: Structure React applications with one folder per component following the pattern: ComponentName/ComponentName.tsx with index.ts barrel export
Co-locate component dependencies (hooks, utils, constants, tests, stories) next to the file using them
Files:
apps/desktop/electron-builder.ts
apps/desktop/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
For Electron interprocess communication, ALWAYS use tRPC as defined in
src/lib/trpc
Files:
apps/desktop/electron-builder.ts
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: Please use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary
Files:
apps/desktop/electron-builder.ts
🪛 actionlint (1.7.9)
.github/workflows/release-desktop.yml
128-128: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Build - macOS (arm64)
🔇 Additional comments (1)
apps/desktop/electron-builder.ts (1)
22-23:publish: nullis the right way to disable electron‑builder auto‑publish.This cleanly hands off publishing to the GitHub Actions workflow and aligns with the new release script; no issues from the config side.
Description
Related Issues
Type of Change
Testing
Screenshots (if applicable)
Additional Notes
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.