Skip to content
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
14 changes: 14 additions & 0 deletions .github/workflows/publish-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,17 @@ jobs:
working-directory: crates/bashkit-js
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Verify npm publish
run: |
sleep 10
PKG_VERSION=$(node -p "require('./package.json').version")
ACTUAL=$(npm view @everruns/bashkit version 2>/dev/null || echo "not found")
if [ "$ACTUAL" = "$PKG_VERSION" ]; then
echo "✓ @everruns/bashkit@$ACTUAL published to npm (latest)"
else
echo "✗ expected $PKG_VERSION on npm latest, got $ACTUAL"
echo "::error::npm publish verification failed"
exit 1
fi
working-directory: crates/bashkit-js
53 changes: 47 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,27 @@ jobs:
fi

- name: Strip git-only dependencies for publishing
# monty is a git dep (not yet on crates.io) — remove before publish
# monty is a git dep (not yet on crates.io) — remove before publish.
# Must strip from both bashkit AND bashkit-cli because cargo resolves
# the whole workspace when publishing a single crate.
run: |
# --- bashkit core ---
TOML=crates/bashkit/Cargo.toml
# Remove monty dependency line
sed -i '/^monty = .*/d' "$TOML"
# Remove python feature that references monty
sed -i '/^python = \["dep:monty"\]/d' "$TOML"
# Remove python_scripts example block (requires python feature)
sed -i '/^\[\[example\]\]/{N;N;/python_scripts/d}' "$TOML"
echo "--- Cargo.toml after stripping ---"
echo "--- bashkit Cargo.toml after stripping ---"
cat "$TOML"

# --- bashkit-cli (workspace resolution requires this too) ---
CLI_TOML=crates/bashkit-cli/Cargo.toml
sed -i '/^python = \["bashkit\/python"\]/d' "$CLI_TOML"
sed -i 's/default = \["python"\]/default = []/' "$CLI_TOML"
echo "--- bashkit-cli Cargo.toml after stripping ---"
cat "$CLI_TOML"

- name: Publish bashkit to crates.io
run: cargo publish -p bashkit --allow-dirty 2>&1 || echo "::warning::bashkit publish failed (may already exist)"
run: cargo publish -p bashkit --allow-dirty
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

Expand Down Expand Up @@ -84,3 +91,37 @@ jobs:
run: cargo publish -p bashkit-cli --allow-dirty
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

# ============================================================================
# Verify all packages were published successfully
# ============================================================================
verify-publish:
name: Verify published versions
runs-on: ubuntu-latest
needs: [publish-bashkit, publish-bashkit-cli]
steps:
- uses: actions/checkout@v6

- name: Wait for crates.io propagation
run: sleep 60

- name: Verify crates.io versions
run: |
EXPECTED=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
echo "Expected version: $EXPECTED"
PASS=true

for CRATE in bashkit bashkit-cli; do
ACTUAL=$(curl -s "https://crates.io/api/v1/crates/$CRATE" | python3 -c "import sys,json; print(json.load(sys.stdin)['crate']['max_version'])")
if [ "$ACTUAL" = "$EXPECTED" ]; then
echo "✓ $CRATE@$ACTUAL on crates.io"
else
echo "✗ $CRATE: expected $EXPECTED, got $ACTUAL"
PASS=false
fi
done

if [ "$PASS" = "false" ]; then
echo "::error::Some crates.io packages were not published correctly"
exit 1
fi
30 changes: 26 additions & 4 deletions specs/008-release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ When asked to create a release, the agent:
- Extracts release notes from CHANGELOG.md
- Creates GitHub Release with tag `vX.Y.Z`

**On GitHub Release published** (publish.yml):
- Publishes to crates.io in dependency order
- Note: No verification step - CI already ran when PR merged to main
**On GitHub Release published** (publish.yml, publish-js.yml, publish-python.yml):
- Publishes to crates.io, npm, and PyPI
- Each publish workflow includes a verification step that checks the published version matches expectations

## Pre-Release Checklist

Expand Down Expand Up @@ -199,7 +199,7 @@ brew install everruns/tap/bashkit
### publish.yml

- **Trigger**: GitHub Release published
- **Actions**: Publishes to crates.io (no verification - CI ran on merge)
- **Actions**: Publishes to crates.io in dependency order, then verifies published versions
- **File**: `.github/workflows/publish.yml`
- **Secret required**: `CARGO_REGISTRY_TOKEN`

Expand Down Expand Up @@ -294,6 +294,28 @@ Done. PR created: https://github.com/everruns/bashkit/pull/XX
Please review and merge to trigger the release.
```

## Post-Release Verification

Each publish workflow includes automated verification. After a release, the agent (or human) should also verify manually:

```bash
# crates.io
cargo search bashkit # Should show latest version
cargo search bashkit-cli # Should show latest version

# npm
npm view @everruns/bashkit version # Should show latest version
npm dist-tags ls @everruns/bashkit # "latest" should point to new version

# PyPI
pip index versions bashkit # Should show latest version

# GitHub
gh release view --repo everruns/bashkit # Should show latest tag
```

If any registry is missing the new version, check the corresponding publish workflow run for errors.

## Hotfix Releases

For urgent fixes:
Expand Down
Loading