Skip to content

fix: update version validation to allow pre-release and build metadat… #6

fix: update version validation to allow pre-release and build metadat…

fix: update version validation to allow pre-release and build metadat… #6

Workflow file for this run

# Release Workflow
#
# This workflow automates the release process when semantic version tags are pushed.
# It reuses build artifacts from the build workflow (must merge to main first), validates
# the version, creates GitHub releases, and publishes to package managers.
#
# IMPORTANT: Tags must be on commits that have been merged to main and built by build.yml
#
# Triggers: Push of semantic version tag (e.g., v1.2.3)
# Performance Target: ≤10 minutes total (excluding manual approval)
# Artifacts: Reuses build artifacts, creates release packages
#
# Manual Testing on PR:
# 1. Run Build workflow manually on your PR branch first
# 2. Note the commit SHA from the build run
# 3. Use Actions tab → Release → Run workflow
# - Select your PR branch
# - Enter test version (e.g., v0.0.1-test)
# - Check 'Skip Homebrew' to avoid tap updates
# - Check 'Dry run' to skip actual release creation
# 4. Review logs to verify workflow logic
#
# Production Release:
# 1. Merge PR to main → triggers build.yml automatically
# 2. Wait for build to complete successfully
# 3. Tag the merge commit: git tag v1.0.0 && git push origin v1.0.0
# 4. Release workflow triggers automatically
name: Release
on:
push:
tags:
- 'v*.*.*' # Semantic version tags only (e.g., v1.2.3, v0.1.0)
workflow_dispatch: # Allow manual triggering for testing
inputs:
tag:
description: 'Version tag to release (e.g., v0.0.1-test for testing)'
required: true
type: string
skip_homebrew:
description: 'Skip Homebrew publication (for PR testing)'
required: false
type: boolean
default: false
dry_run:
description: 'Dry run - skip release creation (logs only)'
required: false
type: boolean
default: false
# Prevent concurrent releases to avoid conflicts
# Do not cancel in-progress releases as they involve publishing to external services
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
# Workflow-level permissions
permissions:
contents: write # Required for creating releases and reading repo
actions: read # Required for downloading artifacts from build workflow
packages: write # Required for GitHub Packages (bottles)
issues: write # Required for creating Winget/Chocolatey publication issues
jobs:
# Job 1: Validate Version and Find Artifacts
# Extract/validate version, ensure tag is on main, find build artifacts
# Performance Target: <2 minutes
validate-version:
name: Validate Version & Find Artifacts
runs-on: ubuntu-latest
outputs:
version: ${{ steps.extract.outputs.version }}
commit-sha: ${{ steps.validate.outputs.commit-sha }}
build-run-id: ${{ steps.find-artifacts.outputs.run-id }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for release notes
- name: Extract version from tag
id: extract
run: |
# Get tag name (either from push event or manual input)
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG_NAME="${{ github.event.inputs.tag }}"
else
TAG_NAME="${GITHUB_REF#refs/tags/}"
fi
# Remove 'v' prefix to get version
VERSION="${TAG_NAME#v}"
echo "📦 Tag: $TAG_NAME"
echo "🔢 Version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Validate semantic version format
run: |
VERSION="${{ steps.extract.outputs.version }}"
# Allow semver with optional pre-release/build metadata
# Valid formats: 1.2.3, 1.2.3-beta.1, 1.2.3+build.123, 1.2.3-rc.1+build.456
if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$'; then
echo "❌ Error: Invalid semantic version format: $VERSION"
echo "Expected format: MAJOR.MINOR.PATCH with optional pre-release and build metadata"
echo "Examples: 1.2.3, 0.1.0-beta.1, 1.0.0-rc.1+build.123"
exit 1
fi
echo "✅ Valid version format: $VERSION"
- name: Validate tag is on main branch
id: validate
run: |
# Get the commit SHA for this tag
COMMIT_SHA=$(git rev-list -n 1 ${{ github.ref }})
echo "commit-sha=$COMMIT_SHA" >> $GITHUB_OUTPUT
echo "📍 Tag commit: $COMMIT_SHA"
# For manual testing, allow any branch
# For production tag push, enforce main branch only
if [ "${{ github.event_name }}" = "push" ]; then
# Check if this commit is on main branch
if ! git branch -r --contains $COMMIT_SHA | grep -q "origin/main"; then
echo "❌ Error: Tag must be on a commit that exists on main branch"
echo "Please merge to main first, then tag the merge commit"
exit 1
fi
echo "✅ Tag is on main branch"
else
echo "⚠️ Manual dispatch: Skipping main branch check"
echo "✅ Running on branch: ${{ github.ref_name }}"
fi
- name: Check for duplicate version in releases
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION="${{ steps.extract.outputs.version }}"
# Check if this version already exists as a release
if gh release view "v$VERSION" &>/dev/null; then
# For test versions, just warn instead of failing
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && echo "$VERSION" | grep -q -- "-"; then
echo "⚠️ Warning: Release v$VERSION already exists (test version)"
echo "💡 Consider using a different test version or deleting the existing one"
else
echo "❌ Error: Release v$VERSION already exists"
echo "Please use a new version number"
exit 1
fi
else
echo "✅ Version v$VERSION is unique"
fi
- name: Find build workflow artifacts
id: find-artifacts
env:
GH_TOKEN: ${{ github.token }}
run: |
COMMIT_SHA="${{ steps.validate.outputs.commit-sha }}"
echo "🔍 Looking for build workflow run for commit $COMMIT_SHA..."
# Find the build workflow run for this commit
RUN_ID=$(gh run list \
--workflow=build.yml \
--commit=$COMMIT_SHA \
--status=success \
--json databaseId \
--jq '.[0].databaseId')
if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then
echo "❌ Error: No successful build workflow run found for commit $COMMIT_SHA"
echo ""
echo "The release workflow reuses artifacts from the build workflow to avoid redundancy."
echo "Please ensure:"
echo " 1. Code has been merged to main branch"
echo " 2. Build workflow has completed successfully"
echo " 3. Tag is created on the same commit that was built"
echo ""
echo "Typical workflow:"
echo " 1. Merge PR to main → triggers build.yml"
echo " 2. Wait for build to complete"
echo " 3. Tag the merge commit: git tag v1.0.0 && git push origin v1.0.0"
exit 1
fi
echo "run-id=$RUN_ID" >> $GITHUB_OUTPUT
echo "✅ Found build workflow run: $RUN_ID"
echo "🔗 https://github.com/${{ github.repository }}/actions/runs/$RUN_ID"
# Job 2: Download Build Artifacts
# Reuse artifacts from the build workflow to avoid redundant builds
# Performance Target: <1 minute
download-artifacts:
name: Download Build Artifacts
runs-on: ubuntu-latest
needs: validate-version
steps:
- name: Download artifacts from build workflow
env:
GH_TOKEN: ${{ github.token }}
run: |
RUN_ID="${{ needs.validate-version.outputs.build-run-id }}"
echo "📥 Downloading artifacts from build run $RUN_ID..."
# Download all three platform artifacts
gh run download $RUN_ID \
--repo ${{ github.repository }} \
--dir ./artifacts
echo "✅ Downloaded artifacts:"
ls -lah ./artifacts/
# Verify all expected artifacts exist
for artifact in ten-second-tom-osx-x64 ten-second-tom-osx-arm64 ten-second-tom-win-x64; do
if [ ! -d "./artifacts/$artifact" ]; then
echo "❌ Error: Expected artifact '$artifact' not found"
exit 1
fi
echo " ✅ $artifact"
done
- name: Upload artifacts for release jobs
uses: actions/upload-artifact@v4
with:
name: release-artifacts
path: ./artifacts/
retention-days: 90
# Job 3: Create GitHub Release
# Generate release notes and create GitHub release with all binaries
# Performance Target: ≤2 minutes
create-github-release:
name: Create GitHub Release
runs-on: ubuntu-latest
needs: [validate-version, download-artifacts]
outputs:
release-id: ${{ steps.create-release.outputs.id }}
upload-url: ${{ steps.create-release.outputs.upload_url }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for release notes
- name: Download release artifacts
uses: actions/download-artifact@v4
with:
name: release-artifacts
path: ./artifacts
- name: Generate release notes
id: release-notes
run: |
VERSION="v${{ needs.validate-version.outputs.version }}"
# Get previous tag for changelog
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
if [ -z "$PREV_TAG" ]; then
echo "📝 First release - no previous tag found"
NOTES="## 🎉 Initial Release
This is the first release of Ten Second Tom.
### 📦 Downloads
Choose the appropriate binary for your platform:
- **macOS (Intel)**: \`tom\` (from ten-second-tom-osx-x64)
- **macOS (Apple Silicon)**: \`tom\` (from ten-second-tom-osx-arm64)
- **Windows**: \`tom.exe\` (from ten-second-tom-win-x64)
### ✅ Verification
Use \`shasum -a 256\` or \`Get-FileHash\` to verify the downloaded binaries."
else
echo "📝 Generating changelog from $PREV_TAG to $VERSION"
# Generate commit log
COMMITS=$(git log $PREV_TAG..HEAD --pretty=format:"- %s (%h)" --no-merges)
NOTES="## 📋 Changes
$COMMITS
### 📦 Downloads
Choose the appropriate binary for your platform:
- **macOS (Intel)**: \`tom\` (from ten-second-tom-osx-x64)
- **macOS (Apple Silicon)**: \`tom\` (from ten-second-tom-osx-arm64)
- **Windows**: \`tom.exe\` (from ten-second-tom-win-x64)
### ✅ Verification
Use \`shasum -a 256\` or \`Get-FileHash\` to verify the downloaded binaries."
fi
# Save notes to file (handle multiline)
echo "$NOTES" > release-notes.md
cat release-notes.md
- name: Create GitHub Release
id: create-release
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION="v${{ needs.validate-version.outputs.version }}"
# Check if this is a dry run
if [ "${{ github.event.inputs.dry_run }}" = "true" ]; then
echo "🧪 DRY RUN - Would create release $VERSION"
echo "📝 Release notes:"
cat release-notes.md
echo "⏭️ Skipping actual release creation"
exit 0
fi
# Create release with notes
gh release create "$VERSION" \
--title "Release $VERSION" \
--notes-file release-notes.md \
--draft=false \
--latest
echo "✅ GitHub release created: $VERSION"
# Check if this is a dry run
if [ "${{ github.event.inputs.dry_run }}" = "true" ]; then
echo "🧪 DRY RUN - Skipping artifact uploads"
exit 0
fi
# Upload all artifacts
echo "📤 Uploading artifacts..."
# Upload macOS x64
gh release upload "$VERSION" \
./artifacts/ten-second-tom-osx-x64/tom \
--clobber
# Upload macOS ARM64
gh release upload "$VERSION" \
./artifacts/ten-second-tom-osx-arm64/tom \
--clobber
# Upload Windows x64
gh release upload "$VERSION" \
./artifacts/ten-second-tom-win-x64/tom.exe \
--clobber
echo "✅ All artifacts uploaded"
# Job 4: Publish to Homebrew with Bottles
# Create Homebrew bottles and upload to GitHub Packages, then update tap formula
# Performance Target: ≤7 minutes
# Requires: HOMEBREW_TAP_TOKEN secret configured in 'production' environment
# Note: VS Code may show "'production' is not valid" - this is a false positive
# Can be skipped with workflow_dispatch skip_homebrew input for PR testing
publish-homebrew:
name: Publish to Homebrew
runs-on: macos-latest # Changed to macOS for bottle creation
needs: [validate-version, create-github-release]
if: ${{ github.event.inputs.skip_homebrew != 'true' && github.event.inputs.dry_run != 'true' }}
environment:
name: production # Configured in GitHub repository settings
permissions:
contents: read
packages: write # Required for GitHub Packages (bottles)
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download release artifacts
uses: actions/download-artifact@v4
with:
name: release-artifacts
path: ./artifacts
- name: Create Homebrew bottles
id: bottles
run: |
VERSION="${{ needs.validate-version.outputs.version }}"
REPO_OWNER="${{ github.repository_owner }}"
echo "🍾 Creating Homebrew bottles for version $VERSION"
# Determine macOS version for bottle tag (e.g., arm64_monterey, monterey)
MACOS_VERSION=$(sw_vers -productVersion | cut -d '.' -f 1)
case $MACOS_VERSION in
12) MACOS_TAG="monterey" ;;
13) MACOS_TAG="ventura" ;;
14) MACOS_TAG="sonoma" ;;
15) MACOS_TAG="sequoia" ;;
*) MACOS_TAG="monterey" ;; # Default fallback
esac
# Detect current architecture
ARCH=$(uname -m)
if [ "$ARCH" = "arm64" ]; then
BOTTLE_TAG="arm64_${MACOS_TAG}"
BINARY_PATH="./artifacts/ten-second-tom-osx-arm64/tom"
CHECKSUM_PATH="./artifacts/ten-second-tom-osx-arm64/checksum.txt"
else
BOTTLE_TAG="${MACOS_TAG}"
BINARY_PATH="./artifacts/ten-second-tom-osx-x64/tom"
CHECKSUM_PATH="./artifacts/ten-second-tom-osx-x64/checksum.txt"
fi
echo "📦 Building bottle for $BOTTLE_TAG"
# Create bottle directory structure
BOTTLE_DIR="ten-second-tom/${VERSION}/bin"
mkdir -p "$BOTTLE_DIR"
# Copy binary
cp "$BINARY_PATH" "$BOTTLE_DIR/tom"
chmod +x "$BOTTLE_DIR/tom"
# Create bottle tarball
BOTTLE_NAME="ten-second-tom--${VERSION}.${BOTTLE_TAG}.bottle.tar.gz"
tar czf "$BOTTLE_NAME" -C . ten-second-tom
# Calculate bottle SHA256
BOTTLE_SHA=$(shasum -a 256 "$BOTTLE_NAME" | cut -d ' ' -f 1)
echo "✅ Bottle created: $BOTTLE_NAME"
echo " SHA256: $BOTTLE_SHA"
# Output variables for later steps
echo "bottle-name=$BOTTLE_NAME" >> $GITHUB_OUTPUT
echo "bottle-tag=$BOTTLE_TAG" >> $GITHUB_OUTPUT
echo "bottle-sha=$BOTTLE_SHA" >> $GITHUB_OUTPUT
# Calculate checksums for both architectures directly from binaries
SHA256_X64=$(shasum -a 256 ./artifacts/ten-second-tom-osx-x64/tom | cut -d ' ' -f 1)
SHA256_ARM64=$(shasum -a 256 ./artifacts/ten-second-tom-osx-arm64/tom | cut -d ' ' -f 1)
echo "sha256-x64=$SHA256_X64" >> $GITHUB_OUTPUT
echo "sha256-arm64=$SHA256_ARM64" >> $GITHUB_OUTPUT
echo " x64 SHA256: $SHA256_X64"
echo " ARM64 SHA256: $SHA256_ARM64"
- name: Upload bottle to GitHub Packages
run: |
VERSION="${{ needs.validate-version.outputs.version }}"
REPO_OWNER="${{ github.repository_owner }}"
BOTTLE_NAME="${{ steps.bottles.outputs.bottle-name }}"
echo "📤 Uploading bottle to GitHub Packages (ghcr.io)"
# Login to GitHub Container Registry
echo "${{ github.token }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
# Use GitHub CLI to upload as package
# Note: For Homebrew bottles, we use GitHub Packages generic packages
# The bottle will be available at: ghcr.io/v2/$REPO_OWNER/tom/bottles/$BOTTLE_NAME
# Create package metadata
PACKAGE_NAME="tom"
PACKAGE_URL="ghcr.io/${REPO_OWNER}/${PACKAGE_NAME}"
# Upload using oras (OCI Registry As Storage) or curl to GitHub Packages API
# For simplicity, we'll attach to the release as well and document the ghcr.io URL
# Upload to GitHub release as backup
gh release upload "v${VERSION}" "$BOTTLE_NAME" --clobber
echo "✅ Bottle uploaded to release assets"
echo "📦 Bottle available at: https://github.com/${REPO_OWNER}/${{ github.event.repository.name }}/releases/download/v${VERSION}/${BOTTLE_NAME}"
- name: Generate Homebrew formula with bottle blocks
id: formula
run: |
VERSION="${{ needs.validate-version.outputs.version }}"
REPO_OWNER="${{ github.repository_owner }}"
REPO_NAME="${{ github.event.repository.name }}"
BOTTLE_TAG="${{ steps.bottles.outputs.bottle-tag }}"
BOTTLE_SHA="${{ steps.bottles.outputs.bottle-sha }}"
SHA256_X64="${{ steps.bottles.outputs.sha256-x64 }}"
SHA256_ARM64="${{ steps.bottles.outputs.sha256-arm64 }}"
echo "📝 Generating Homebrew formula for version $VERSION with bottle support"
# Create formula file with bottle block
cat > ten-second-tom.rb <<FORMULA
class TenSecondTom < Formula
desc "CLI tool for daily work summaries using Claude AI"
homepage "https://github.com/${REPO_OWNER}/${REPO_NAME}"
url "https://github.com/${REPO_OWNER}/${REPO_NAME}/archive/refs/tags/v${VERSION}.tar.gz"
version "${VERSION}"
license "MIT"
# Bottles (pre-built binaries) for fast installation
bottle do
root_url "https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/v${VERSION}"
sha256 cellar: :any_skip_relocation, arm64_monterey: "${SHA256_ARM64}"
sha256 cellar: :any_skip_relocation, monterey: "${SHA256_X64}"
end
def install
bin.install "tom"
end
test do
system "#{bin}/tom", "--version"
end
end
FORMULA
cat ten-second-tom.rb
- name: Validate formula syntax
run: |
echo "✅ Formula syntax validation (basic check)"
# Basic syntax validation - full validation requires Homebrew installation
if ! grep -q "class TenSecondTom" ten-second-tom.rb; then
echo "❌ Error: Invalid formula structure"
exit 1
fi
if ! grep -q "version \"${{ needs.validate-version.outputs.version }}\"" ten-second-tom.rb; then
echo "❌ Error: Version not found in formula"
exit 1
fi
if ! grep -q "bottle do" ten-second-tom.rb; then
echo "❌ Error: Bottle block not found in formula"
exit 1
fi
echo "✅ Basic formula validation passed (including bottle block)"
- name: Push formula to Homebrew tap
env:
# Note: This secret is configured in the 'production' environment
# Go to Settings → Environments → production → Environment secrets
TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
if [ -z "$TAP_TOKEN" ]; then
echo "❌ Error: HOMEBREW_TAP_TOKEN secret not configured"
echo "Please configure the secret in the 'production' environment"
echo "Settings → Environments → production → Environment secrets"
exit 1
fi
VERSION="${{ needs.validate-version.outputs.version }}"
REPO_OWNER="${{ github.repository_owner }}"
TAP_REPO="homebrew-ten-second-tom"
echo "📤 Pushing formula with bottles to ${REPO_OWNER}/${TAP_REPO}"
# Clone tap repository
git clone "https://x-access-token:${TAP_TOKEN}@github.com/${REPO_OWNER}/${TAP_REPO}.git" tap-repo
cd tap-repo
# Configure git
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Copy formula
mkdir -p Formula
cp ../ten-second-tom.rb Formula/ten-second-tom.rb
# Commit and push
git add Formula/ten-second-tom.rb
git commit -m "Release version ${VERSION} with bottles"
git push origin main
echo "✅ Formula with bottle support published to Homebrew tap"
# Job 5: Document Winget Publication
# Generate Winget manifest and create issue for manual publication (Phase 1)
# Performance Target: <1 minute
# Note: Phase 2 will automate the publication process
document-winget:
name: Document Winget Publication
runs-on: ubuntu-latest
needs: [validate-version, create-github-release]
if: success() # Run even if other jobs fail
steps:
- name: Generate Winget manifest template
run: |
VERSION="${{ needs.validate-version.outputs.version }}"
REPO_OWNER="${{ github.repository_owner }}"
REPO_NAME="${{ github.event.repository.name }}"
cat > winget-manifest.yaml <<EOF
# Winget Package Manifest
# This manifest should be submitted to microsoft/winget-pkgs repository
# Manual submission process (Phase 1) - will be automated in Phase 2
PackageIdentifier: ${REPO_OWNER}.TenSecondTom
PackageVersion: ${VERSION}
PackageName: Ten Second Tom
Publisher: ${REPO_OWNER}
License: MIT
ShortDescription: CLI tool for daily work summaries using Claude AI
PackageUrl: https://github.com/${REPO_OWNER}/${REPO_NAME}
Installers:
- Architecture: x64
InstallerType: zip
InstallerUrl: https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/v${VERSION}/tom.exe
# TODO: Add SHA256 checksum from release artifact
ManifestType: singleton
ManifestVersion: 1.0.0
EOF
cat winget-manifest.yaml
- name: Create GitHub issue for manual publication
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION="${{ needs.validate-version.outputs.version }}"
gh issue create \
--repo ${{ github.repository }} \
--title "📦 Publish v${VERSION} to Winget" \
--body "## Manual Winget Publication Required
Version **v${VERSION}** has been released and needs to be published to Winget.
### Steps:
1. Fork microsoft/winget-pkgs repository
2. Use the generated manifest template (see workflow artifacts)
3. Create a PR to microsoft/winget-pkgs
4. Wait for validation and merge
### References:
- [Winget Package Manifest](https://github.com/microsoft/winget-pkgs)
- [Release v${VERSION}](https://github.com/${{ github.repository }}/releases/tag/v${VERSION})
### Automation:
Phase 2 will automate this process." \
--label "release,winget" || echo "⚠️ Issue creation skipped (may already exist)"
# Job 6: Document Chocolatey Publication
# Generate Chocolatey nuspec and create issue for manual publication (Phase 1)
# Performance Target: <1 minute
# Note: Phase 2 will automate the publication process
document-chocolatey:
name: Document Chocolatey Publication
runs-on: ubuntu-latest
needs: [validate-version, create-github-release]
if: success() # Run even if other jobs fail
steps:
- name: Generate Chocolatey nuspec template
run: |
VERSION="${{ needs.validate-version.outputs.version }}"
REPO_OWNER="${{ github.repository_owner }}"
REPO_NAME="${{ github.event.repository.name }}"
cat > ten-second-tom.nuspec <<EOF
<?xml version="1.0" encoding="utf-8"?>
<!-- Chocolatey Package Specification -->
<!-- Manual submission process (Phase 1) - will be automated in Phase 2 -->
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
<metadata>
<id>ten-second-tom</id>
<version>${VERSION}</version>
<title>Ten Second Tom</title>
<authors>${REPO_OWNER}</authors>
<projectUrl>https://github.com/${REPO_OWNER}/${REPO_NAME}</projectUrl>
<licenseUrl>https://github.com/${REPO_OWNER}/${REPO_NAME}/blob/main/LICENSE</licenseUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>CLI tool for daily work summaries using Claude AI</description>
<summary>Daily work summary CLI powered by Claude AI</summary>
<tags>cli productivity ai claude summary</tags>
</metadata>
<files>
<file src="tools\**" target="tools" />
</files>
</package>
EOF
cat ten-second-tom.nuspec
- name: Create GitHub issue for manual publication
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION="${{ needs.validate-version.outputs.version }}"
gh issue create \
--repo ${{ github.repository }} \
--title "📦 Publish v${VERSION} to Chocolatey" \
--body "## Manual Chocolatey Publication Required
Version **v${VERSION}** has been released and needs to be published to Chocolatey.
### Steps:
1. Create Chocolatey account (if not exists)
2. Use the generated nuspec template (see workflow artifacts)
3. Package and test locally: \`choco pack\`
4. Publish: \`choco push ten-second-tom.${VERSION}.nupkg --source https://push.chocolatey.org/\`
### References:
- [Chocolatey Package Docs](https://docs.chocolatey.org/en-us/create/create-packages)
- [Release v${VERSION}](https://github.com/${{ github.repository }}/releases/tag/v${VERSION})
### Automation:
Phase 2 will automate this process." \
--label "release,chocolatey" || echo "⚠️ Issue creation skipped (may already exist)"