-
Notifications
You must be signed in to change notification settings - Fork 938
create release script #144
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
Changes from all commits
d4dfa3a
ad7d830
78ba905
c5bc85d
65bad36
fd49f51
ec89aa5
e677f1b
f1e2ef9
c704e5e
47f5408
1aed654
4db85c8
89a9741
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,273 @@ | ||
| #!/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. Delete existing release/tag if republishing same version | ||
| # 3. Update package.json version | ||
| # 4. Create and push a git tag to trigger the release workflow | ||
| # 5. Monitor the GitHub Actions workflow in real-time | ||
| # 6. Auto-publish the release when build completes | ||
| # | ||
| # Features: | ||
| # - Supports republishing: Running with same version will clean up and rebuild | ||
| # - Auto-publishes release (no manual publish step needed) | ||
| # | ||
| # 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..." | ||
| if ! git diff-index --quiet HEAD --; then | ||
| error "You have uncommitted changes. Please commit or stash them first." | ||
| fi | ||
| success "Working directory is clean" | ||
|
|
||
| # 2. Check if tag/release already exists | ||
| info "Checking if tag ${TAG_NAME} already exists..." | ||
| if git rev-parse "${TAG_NAME}" >/dev/null 2>&1; then | ||
| echo "" | ||
| warn "Tag ${TAG_NAME} already exists!" | ||
|
|
||
| # Check if there's also a GitHub release | ||
| if gh release view "${TAG_NAME}" &>/dev/null; then | ||
| RELEASE_STATUS=$(gh release view "${TAG_NAME}" --json isDraft --jq 'if .isDraft then "draft" else "published"' 2>/dev/null || echo "unknown") | ||
| echo -e " GitHub release: ${YELLOW}${RELEASE_STATUS}${NC}" | ||
| else | ||
| echo -e " GitHub release: ${YELLOW}none${NC}" | ||
| fi | ||
| echo "" | ||
|
|
||
| # Ask user what to do | ||
| echo "What would you like to do?" | ||
| echo " 1) Republish - Delete existing release/tag and create new one" | ||
| echo " 2) Cancel - Exit without changes" | ||
| echo "" | ||
| read -p "Enter choice [1-2]: " choice | ||
|
|
||
| case $choice in | ||
| 1) | ||
| info "Cleaning up for republish..." | ||
|
|
||
| # Delete the GitHub release if it exists | ||
| if gh release view "${TAG_NAME}" &>/dev/null; then | ||
| info "Deleting existing GitHub release..." | ||
| gh release delete "${TAG_NAME}" --yes | ||
| success "Deleted existing release" | ||
| fi | ||
|
|
||
| # Delete remote tag | ||
| info "Deleting remote tag..." | ||
| git push origin --delete "${TAG_NAME}" 2>/dev/null || true | ||
| success "Deleted remote tag" | ||
|
|
||
| # Delete local tag | ||
| info "Deleting local tag..." | ||
| git tag -d "${TAG_NAME}" 2>/dev/null || true | ||
| success "Deleted local tag" | ||
| ;; | ||
| 2|*) | ||
| info "Cancelled. No changes made." | ||
| exit 0 | ||
| ;; | ||
| esac | ||
| fi | ||
| success "Tag ${TAG_NAME} is available" | ||
|
|
||
| # 3. Update version in package.json | ||
| info "Updating version in package.json..." | ||
| CURRENT_VERSION=$(node -p "require('./package.json').version") | ||
| if [ "${CURRENT_VERSION}" == "${VERSION}" ]; then | ||
| warn "package.json already has version ${VERSION}" | ||
| else | ||
| # Update the version using jq to handle workspace dependencies | ||
| TMP_FILE=$(mktemp) | ||
| jq ".version = \"${VERSION}\"" package.json > "${TMP_FILE}" && mv "${TMP_FILE}" package.json | ||
|
Comment on lines
+149
to
+150
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add error handling for jq operations. The temporary file and jq pipeline on lines 100–101 lack error handling. If 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.
🤖 Prompt for AI Agents |
||
| 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 "" | ||
|
|
||
| # 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) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainScript 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> stdout: </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> stdout: </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> stdout: </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> stdout: </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> stdout: </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> stderr: </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> stdout: </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> stderr: </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> stderr: </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> </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> stdout: </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> stdout: </shell_result> Script executed: #!/bin/bash
# Read the RELEASE.md file
cat -n apps/desktop/RELEASE.mdRepository: superset-sh/superset <shell_result> stdout: </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> stderr: </shell_result> GitHub Actions API workflow run headBranch field tag push trigger <web_search_result> Why / how to handle it
References
GitHub Actions API headRefName field tag workflow runs <web_search_result> Sources:
References: Workflow detection filter is incompatible with tag-triggered runs. Line 145 filters by Available fields in Suggested investigation: query a recent run using 🤖 Prompt for AI Agents |
||
| 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 | ||
|
Comment on lines
+183
to
+228
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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 Once the filter bug on line 145 is fixed, this section should work correctly. 🤖 Prompt for AI Agents |
||
|
|
||
| echo "" | ||
|
|
||
| # 7. Wait for release and publish it | ||
| info "Waiting for draft release to be created..." | ||
|
|
||
| # Retry logic for draft release (it may take time to be created) | ||
| MAX_RELEASE_RETRIES=10 | ||
| RELEASE_RETRY_COUNT=0 | ||
| RELEASE_FOUND="" | ||
|
|
||
| while [ $RELEASE_RETRY_COUNT -lt $MAX_RELEASE_RETRIES ] && [ -z "$RELEASE_FOUND" ]; do | ||
| sleep 3 | ||
| RELEASE_FOUND=$(gh release list --json tagName,isDraft --jq ".[] | select(.tagName == \"${TAG_NAME}\") | .tagName") | ||
| RELEASE_RETRY_COUNT=$((RELEASE_RETRY_COUNT + 1)) | ||
|
|
||
| if [ -z "$RELEASE_FOUND" ] && [ $RELEASE_RETRY_COUNT -lt $MAX_RELEASE_RETRIES ]; then | ||
| echo " Waiting for release to be created... (attempt $RELEASE_RETRY_COUNT/$MAX_RELEASE_RETRIES)" | ||
| fi | ||
| done | ||
|
|
||
| if [ -z "$RELEASE_FOUND" ]; then | ||
| warn "Release not found yet. It may still be processing." | ||
| echo " Check releases at: https://github.com/${REPO}/releases" | ||
| else | ||
| # Publish the release | ||
| info "Publishing release..." | ||
| gh release edit "${TAG_NAME}" --draft=false | ||
| success "Release published!" | ||
|
|
||
| RELEASE_URL="https://github.com/${REPO}/releases/tag/${TAG_NAME}" | ||
| LATEST_URL="https://github.com/${REPO}/releases/latest" | ||
| echo "" | ||
| echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" | ||
| echo -e "${GREEN}🎉 Release Published!${NC}" | ||
| echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" | ||
| echo "" | ||
| echo -e "${BLUE}Release URL:${NC} ${RELEASE_URL}" | ||
| echo -e "${BLUE}Latest URL:${NC} ${LATEST_URL}" | ||
| echo "" | ||
| echo -e "${BLUE}Direct downloads:${NC}" | ||
| echo " • ${LATEST_URL}/download/Superset-${VERSION}-arm64.dmg" | ||
| echo " • ${LATEST_URL}/download/Superset-${VERSION}-arm64-mac.zip" | ||
| echo "" | ||
| fi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix error message formatting.
The error message uses
\nbut theerror()function (line 44–47) doesn't use the-eflag withecho, so escape sequences won't be interpreted. The newline won't render.Apply this diff:
Alternatively, update the
error()function to useecho -e:error() { - echo -e "${RED}✗${NC} $1" + echo -e "${RED}✗${NC} $1" >&2 exit 1 }(The
>&2redirection is also recommended for error output.)📝 Committable suggestion
🤖 Prompt for AI Agents