Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
85d3b4d
update orchestrator stable release
bourgeoa Mar 19, 2026
11b68e1
updated
bourgeoa Mar 19, 2026
485f886
update stable-publish
bourgeoa Mar 19, 2026
4a3b0f1
preflight token
bourgeoa Mar 19, 2026
42e917f
change merge strategy
bourgeoa Mar 19, 2026
b04620c
fix(release): use --admin merge to bypass branch protection review re…
Mar 19, 2026
08bc8fe
test
bourgeoa Mar 20, 2026
db87fda
fix(release): handle expected checks before PR merge
Mar 20, 2026
9dcd803
fix(release): avoid premature admin merge before checks appear
Mar 20, 2026
d2890bc
chore(release): checkpoint blocked-checks issue and fail fast on stal…
Mar 20, 2026
bd0b265
chore(release): print required status check contexts for blocked PRs
Mar 20, 2026
09ab7ba
fix(release): trigger target CI when required checks are missing
Mar 20, 2026
93b14ca
fix(release): trigger PR CI by force-pushing empty commit
Mar 20, 2026
375b0cc
fix(release): clean working tree after force-push before checkout
Mar 20, 2026
2fae4ef
docs: checkpoint successful stable-publish PR merge flow
Mar 20, 2026
4577f64
fix(release): lock dependencies with caret prefix by default to allow…
Mar 20, 2026
3ba97ab
fix(release): commit version bump when gitTag:false so release branch…
Mar 20, 2026
8b1a5ef
refactor(release): delegate stable-publish latest publish to repo CI
Mar 20, 2026
5c1ad7e
pane-registry release
bourgeoa Mar 21, 2026
bc2ef60
release pane-registry xonfig
bourgeoa Mar 21, 2026
476b133
feat(release): wait for repo CI success before npm publish visibility
Mar 21, 2026
7942724
fix(release): always emit release summary even when a repo fails
Mar 21, 2026
a78607d
release from solid-ui
bourgeoa Mar 23, 2026
4d330f3
release from chat-pane
bourgeoa Mar 23, 2026
d9f53fe
release from-folder-pane
bourgeoa Mar 23, 2026
42f380f
from issue-pane
bourgeoa Mar 23, 2026
3a7cf9c
release from solid-panes
bourgeoa Mar 23, 2026
b2d0782
remove broke build step
bourgeoa Mar 23, 2026
92472e3
remove failing build step without npm ci
bourgeoa Mar 23, 2026
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
17 changes: 16 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ on:
options:
- test
- stable
- stable-prepare-pr
- stable-publish
config:
description: Config file path
required: true
Expand Down Expand Up @@ -46,11 +48,24 @@ jobs:
- name: Update npm to latest
run: npm install -g npm@latest

- name: Preflight GitHub token permissions
env:
GH_TOKEN: ${{ secrets.GIT_PUSH_TOKEN }}
run: |
if [ -z "$GH_TOKEN" ]; then
echo "GIT_PUSH_TOKEN secret is missing" >&2
exit 1
fi
gh --version
gh auth status -h github.com
gh api repos/SolidOS/solid-logic --jq '.full_name + " permissions=" + (if .permissions.push then "push" else "no-push" end)'

- name: Run release orchestrator
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
GITHUB_TOKEN: ${{ secrets.GIT_PUSH_TOKEN }}
GIT_PUSH_TOKEN: ${{ secrets.GIT_PUSH_TOKEN }}
GH_TOKEN: ${{ secrets.GIT_PUSH_TOKEN }}
run: |
BRANCH_ARG=""
if [ -n "${{ inputs.branch }}" ]; then
Expand Down
83 changes: 78 additions & 5 deletions .github/workflows/unpublish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@ on:
description: Exact version to unpublish (e.g. 4.0.5)
required: true
type: string
action:
description: Choose operation (unpublish, deprecate, or auto fallback)
required: true
default: auto
type: choice
options:
- auto
- unpublish
- deprecate
deprecate_message:
description: Message used when deprecating (required for deprecate/auto fallback)
required: true
default: "Deprecated due to release rollback. Please use the latest stable version."
type: string
dry_run:
description: Dry run only (do not execute unpublish)
required: true
Expand Down Expand Up @@ -52,29 +66,88 @@ jobs:
- name: Show target
run: |
echo "Target: ${{ inputs.package_name }}@${{ inputs.version }}"
echo "Action: ${{ inputs.action }}"
echo "Dry run: ${{ inputs.dry_run }}"

- name: Dry run check
if: ${{ inputs.dry_run }}
run: |
echo "Dry run enabled. No unpublish command executed."
echo "Would run: npm unpublish ${{ inputs.package_name }}@${{ inputs.version }} --force"
if [ "${{ inputs.action }}" = "deprecate" ]; then
echo "Would run: npm deprecate -f '${{ inputs.package_name }}@${{ inputs.version }}' '${{ inputs.deprecate_message }}'"
elif [ "${{ inputs.action }}" = "unpublish" ]; then
echo "Would run: npm unpublish ${{ inputs.package_name }}@${{ inputs.version }} --force"
else
echo "Would run: npm unpublish ${{ inputs.package_name }}@${{ inputs.version }} --force"
echo "If blocked by npm policy, would run: npm deprecate -f '${{ inputs.package_name }}@${{ inputs.version }}' '${{ inputs.deprecate_message }}'"
fi

- name: Unpublish exact version
- name: Execute package retirement action
if: ${{ !inputs.dry_run }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
npm unpublish ${{ inputs.package_name }}@${{ inputs.version }} --force
set -euo pipefail
target="${{ inputs.package_name }}@${{ inputs.version }}"
message="${{ inputs.deprecate_message }}"

if [ "${{ inputs.action }}" = "deprecate" ]; then
npm deprecate -f "$target" "$message"
exit 0
fi

if [ "${{ inputs.action }}" = "unpublish" ]; then
npm unpublish "$target" --force
exit 0
fi

set +e
output=$(npm unpublish "$target" --force 2>&1)
status=$?
set -e

- name: Verify version is no longer available
echo "$output"
if [ $status -eq 0 ]; then
echo "Unpublish succeeded."
exit 0
fi

if echo "$output" | grep -qi "You can no longer unpublish this package\|Failed criteria\|E405"; then
echo "Unpublish blocked by npm policy; falling back to deprecate..."
npm deprecate -f "$target" "$message"
exit 0
fi

echo "Unpublish failed for a reason other than npm policy; not falling back."
exit $status

- name: Verify outcome
if: ${{ !inputs.dry_run }}
run: |
if [ "${{ inputs.action }}" = "deprecate" ]; then
npm view ${{ inputs.package_name }}@${{ inputs.version }} deprecated
exit 0
fi

if [ "${{ inputs.action }}" = "auto" ]; then
# In auto mode, either unpublish (version no longer resolves) or deprecate (deprecated message exists) is acceptable.
set +e
npm view ${{ inputs.package_name }}@${{ inputs.version }} version >/dev/null 2>&1
exists_status=$?
set -e
if [ $exists_status -ne 0 ]; then
echo "Version no longer resolvable (unpublished)."
exit 0
fi
npm view ${{ inputs.package_name }}@${{ inputs.version }} deprecated
exit 0
fi

set +e
npm view ${{ inputs.package_name }}@${{ inputs.version }} version
status=$?
if [ $status -eq 0 ]; then
echo "Version still resolvable from npm registry."
echo "Version still resolvable from npm registry (unpublish did not occur)."
exit 1
fi
echo "Unpublish appears successful (version not resolvable)."
74 changes: 41 additions & 33 deletions RELEASE-HOWTO.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ Before the release workflow can publish stable versions from GitHub Actions:
3. In `solidos/solidos` → Settings → Secrets and variables → Actions, add:
- `GIT_PUSH_TOKEN`
- `NPM_TOKEN`
4. Confirm target repos allow the token/account to push to `main`, or decide to use a PR-based merge flow instead.
5. Run the `Solidos Release` workflow manually with:
4. For **protected branches on main**: Use `mode=stable-publish` (no extra config needed—it auto-merges PRs)
5. For **unprotected main branch**: Use `mode=stable` (requires direct push access)
6. Run the `Solidos Release` workflow manually with:
- `mode=test` for prerelease publishing
- `mode=stable` for `@latest`
- `mode=stable-publish` for `@latest` (protected branch)
- `mode=stable` for `@latest` (direct push)

## How It Works

Expand All @@ -40,40 +42,31 @@ Before the release workflow can publish stable versions from GitHub Actions:
|----------|---------|-------|-----------|
| **Local Testing** | `node scripts/release-orchestrator.js --dry-run=true` | Your computer | ❌ No (prints what would happen) |
| **Test Release** | Manual trigger: mode=test | GitHub Actions | ✅ Yes (@test tag) |
| **Stable Release** | Manual trigger: mode=stable | GitHub Actions | ✅ Yes (@latest tag) |
| **Stable Release (Direct Push)** | Manual trigger: mode=stable | GitHub Actions | ✅ Yes (@latest tag) |
| **Stable Release (Protected Branch)** | Manual trigger: mode=stable-publish | GitHub Actions | ✅ Yes (@latest tag, auto-merges PR) |

**Workflow:**
**Workflow (stable-publish mode with protected branches):**
```
You click "Run workflow" button in GitHub Actions (mode=test or mode=stable)
release.yml starts
Runs: node scripts/release-orchestrator.js --mode <test|stable> ...
Script reads release.config.json (list of repos to release)
You click "Run workflow" → mode=stable-publish
↓ Step 1/3: Create Release PR
Creates release branch from dev → Merges dev into main → Pushes branch → Opens PR
↓ Step 2/3: Auto-Merge PR
Waits for CI checks to pass → Auto-merges PR with --squash → Fetches updated main
↓ Step 3/3: Publish
For each repo listed:
- Clone if missing (optional)
- Checkout branch (dev for test, main for stable)
- npm install
- afterInstall with @test or @latest tags (with fallback)

[Stable mode only: Check skip logic]
- Compare origin/dev vs main
- If dev has new commits → merge origin/dev into main with [skip ci]
- If no changes and --branch not specified → skip this repo

[Test mode: always continues]

- npm test
- npm run build
- npm version (bump patch/minor/major/prerelease)
- npm publish (to npm registry with @test or @latest tag)
- git push + tags (stable only)
Generates release-summary.json
- npm version (bump patch/minor/major)
- npm publish (@latest tag)
- git push + tags all at once
```

**Old two-step flow (still supported for manual workflows):**
- Step 1: `mode=stable-prepare-pr` - creates PR, human reviews/merges
- Step 2: `mode=stable-publish` - requires manual merge first

**New unified flow (recommended):**
- Single `mode=stable-publish` - does all three: create PR, auto-merge, publish

## Key Points

- **Individual repos need nothing special** — they just need `package.json` and npm scripts
Expand Down Expand Up @@ -115,15 +108,30 @@ node scripts/release-orchestrator.js --mode test --dry-run=true
- **Always publishes** (no skip logic)
- **Use case:** Pre-release versions for testing from dev branch

**Scenario 3: GitHub Stable Release**
**Scenario 3: GitHub Stable Release (Protected Branches)**
- Click Actions → "Solidos Release" → Run workflow
- Inputs: mode=stable-publish, dry_run=false
- **Single command that does everything:**
1. Creates release branch from dev
2. Opens PR to main
3. Waits for CI checks to pass
4. Auto-merges PR (squash merge)
5. Publishes all packages to npm with `@latest` tag
6. Pushes git tags to main
- Eliminates manual PR merge step
- **Perfect for:** Organizations with branch protection rules on `main`
- **Use case:** Automated stable releases without human intervention on PR merge

**Scenario 4: GitHub Stable Release (Direct Push)**
- Click Actions → "Solidos Release" → Run workflow
- Inputs: mode=stable, dry_run=false
- Automatically merges origin/dev → main if dev has new commits
- Publishes to npm with `@latest` tag
- Creates git tags and pushes to GitHub
- Results in GitHub Actions logs and artifacts
- Skips if dev has no new commits (unless --branch=main specified)
- **Use case:** Production releases to @latest
- **WARNING:** Requires write access to protected branches, may fail with 403
- **Use case:** Repositories without branch protection on `main`

Local dry-run
- Show the exact commands without running them:
Expand Down
Loading
Loading