ha-inlite

Home Assistant integration for in-lite
git clone https://git.stephank.nl/ha-inlite
Log | Files | Refs | README | LICENSE | ZIP

SKILL.md (13646B)


      1 ---
      2 name: "release-process"
      3 description: "Step-by-step release checklist for Squad — prevents v0.8.22-style disasters"
      4 domain: "release-management"
      5 confidence: "high"
      6 source: "team-decision"
      7 ---
      8 
      9 ## Context
     10 
     11 This is the **definitive release runbook** for Squad. Born from the v0.8.22 release disaster (4-part semver mangled by npm, draft release never triggered publish, wrong NPM_TOKEN type, 6+ hours of broken `latest` dist-tag).
     12 
     13 **Rule:** No agent releases Squad without following this checklist. No exceptions. No improvisation.
     14 
     15 ---
     16 
     17 ## Pre-Release Validation
     18 
     19 Before starting ANY release work, validate the following:
     20 
     21 ### 1. Version Number Validation
     22 
     23 **Rule:** Only 3-part semver (major.minor.patch) or prerelease (major.minor.patch-tag.N) are valid. 4-part versions (0.8.21.4) are NOT valid semver and npm will mangle them.
     24 
     25 ```bash
     26 # Check version is valid semver
     27 node -p "require('semver').valid('0.8.22')"
     28 # Output: '0.8.22' = valid
     29 # Output: null = INVALID, STOP
     30 
     31 # For prerelease versions
     32 node -p "require('semver').valid('0.8.23-preview.1')"
     33 # Output: '0.8.23-preview.1' = valid
     34 ```
     35 
     36 **If `semver.valid()` returns `null`:** STOP. Fix the version. Do NOT proceed.
     37 
     38 ### 2. NPM_TOKEN Verification
     39 
     40 **Rule:** NPM_TOKEN must be an **Automation token** (no 2FA required). User tokens with 2FA will fail in CI with EOTP errors.
     41 
     42 ```bash
     43 # Check token type (requires npm CLI authenticated)
     44 npm token list
     45 ```
     46 
     47 Look for:
     48 - ✅ `read-write` tokens with NO 2FA requirement = Automation token (correct)
     49 - ❌ Tokens requiring OTP = User token (WRONG, will fail in CI)
     50 
     51 **How to create an Automation token:**
     52 1. Go to npmjs.com → Settings → Access Tokens
     53 2. Click "Generate New Token"
     54 3. Select **"Automation"** (NOT "Publish")
     55 4. Copy token and save as GitHub secret: `NPM_TOKEN`
     56 
     57 **If using a User token:** STOP. Create an Automation token first.
     58 
     59 ### 3. Branch and Tag State
     60 
     61 **Rule:** Release from `main` branch. Ensure clean state, no uncommitted changes, latest from origin.
     62 
     63 ```bash
     64 # Ensure on main and clean
     65 git checkout main
     66 git pull origin main
     67 git status  # Should show: "nothing to commit, working tree clean"
     68 
     69 # Check tag doesn't already exist
     70 git tag -l "v0.8.22"
     71 # Output should be EMPTY. If tag exists, release already done or collision.
     72 ```
     73 
     74 **If tag exists:** STOP. Either release was already done, or there's a collision. Investigate before proceeding.
     75 
     76 ### 4. Disable bump-build.mjs
     77 
     78 **Rule:** `bump-build.mjs` is for dev builds ONLY. It must NOT run during release builds (it increments build numbers, creating 4-part versions).
     79 
     80 ```bash
     81 # Set env var to skip bump-build.mjs
     82 export SKIP_BUILD_BUMP=1
     83 
     84 # Verify it's set
     85 echo $SKIP_BUILD_BUMP
     86 # Output: 1
     87 ```
     88 
     89 **For Windows PowerShell:**
     90 ```powershell
     91 $env:SKIP_BUILD_BUMP = "1"
     92 ```
     93 
     94 **If not set:** `bump-build.mjs` will run and mutate versions. This causes disasters (see v0.8.22).
     95 
     96 ---
     97 
     98 ## Release Workflow
     99 
    100 ### Step 1: Version Bump
    101 
    102 Update version in all 3 package.json files (root + both workspaces) in lockstep.
    103 
    104 ```bash
    105 # Set target version (no 'v' prefix)
    106 VERSION="0.8.22"
    107 
    108 # Validate it's valid semver BEFORE proceeding
    109 node -p "require('semver').valid('$VERSION')"
    110 # Must output the version string, NOT null
    111 
    112 # Update all 3 package.json files
    113 npm version $VERSION --workspaces --include-workspace-root --no-git-tag-version
    114 
    115 # Verify all 3 match
    116 grep '"version"' package.json packages/squad-sdk/package.json packages/squad-cli/package.json
    117 # All 3 should show: "version": "0.8.22"
    118 ```
    119 
    120 **Checkpoint:** All 3 package.json files have identical versions. Run `semver.valid()` one more time to be sure.
    121 
    122 ### Step 2: Commit and Tag
    123 
    124 ```bash
    125 # Commit version bump
    126 git add package.json packages/squad-sdk/package.json packages/squad-cli/package.json
    127 git commit -m "chore: bump version to $VERSION
    128 
    129 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
    130 
    131 # Create tag (with 'v' prefix)
    132 git tag -a "v$VERSION" -m "Release v$VERSION"
    133 
    134 # Push commit and tag
    135 git push origin main
    136 git push origin "v$VERSION"
    137 ```
    138 
    139 **Checkpoint:** Tag created and pushed. Verify with `git tag -l "v$VERSION"`.
    140 
    141 ### Step 3: Create GitHub Release
    142 
    143 **CRITICAL:** Release must be **published**, NOT draft. Draft releases don't trigger `publish.yml` workflow.
    144 
    145 ```bash
    146 # Create GitHub Release (NOT draft)
    147 gh release create "v$VERSION" \
    148   --title "v$VERSION" \
    149   --notes "Release notes go here" \
    150   --latest
    151 
    152 # Verify release is PUBLISHED (not draft)
    153 gh release view "v$VERSION"
    154 # Output should NOT contain "(draft)"
    155 ```
    156 
    157 **If output contains `(draft)`:** STOP. Delete the release and recreate without `--draft` flag.
    158 
    159 ```bash
    160 # If you accidentally created a draft, fix it:
    161 gh release edit "v$VERSION" --draft=false
    162 ```
    163 
    164 **Checkpoint:** Release is published (NOT draft). The `release: published` event fired and triggered `publish.yml`.
    165 
    166 ### Step 4: Monitor Workflow
    167 
    168 The `publish.yml` workflow should start automatically within 10 seconds of release creation.
    169 
    170 ```bash
    171 # Watch workflow runs
    172 gh run list --workflow=publish.yml --limit 1
    173 
    174 # Get detailed status
    175 gh run view --log
    176 ```
    177 
    178 **Expected flow:**
    179 1. `publish-sdk` job runs → publishes `@bradygaster/squad-sdk`
    180 2. Verify step runs with retry loop (up to 5 attempts, 15s interval) to confirm SDK on npm registry
    181 3. `publish-cli` job runs → publishes `@bradygaster/squad-cli`
    182 4. Verify step runs with retry loop to confirm CLI on npm registry
    183 
    184 **If workflow fails:** Check the logs. Common issues:
    185 - EOTP error = wrong NPM_TOKEN type (use Automation token)
    186 - Verify step timeout = npm propagation delay (retry loop should handle this, but propagation can take up to 2 minutes in rare cases)
    187 - Version mismatch = package.json version doesn't match tag
    188 
    189 **Checkpoint:** Both jobs succeeded. Workflow shows green checkmarks.
    190 
    191 ### Step 5: Verify npm Publication
    192 
    193 Manually verify both packages are on npm with correct `latest` dist-tag.
    194 
    195 ```bash
    196 # Check SDK
    197 npm view @bradygaster/squad-sdk version
    198 # Output: 0.8.22
    199 
    200 npm dist-tag ls @bradygaster/squad-sdk
    201 # Output should show: latest: 0.8.22
    202 
    203 # Check CLI
    204 npm view @bradygaster/squad-cli version
    205 # Output: 0.8.22
    206 
    207 npm dist-tag ls @bradygaster/squad-cli
    208 # Output should show: latest: 0.8.22
    209 ```
    210 
    211 **If versions don't match:** Something went wrong. Check workflow logs. DO NOT proceed with GitHub Release announcement until npm is correct.
    212 
    213 **Checkpoint:** Both packages show correct version. `latest` dist-tags point to the new version.
    214 
    215 ### Step 6: Test Installation
    216 
    217 Verify packages can be installed from npm (real-world smoke test).
    218 
    219 ```bash
    220 # Create temp directory
    221 mkdir /tmp/squad-release-test && cd /tmp/squad-release-test
    222 
    223 # Test SDK installation
    224 npm init -y
    225 npm install @bradygaster/squad-sdk
    226 node -p "require('@bradygaster/squad-sdk/package.json').version"
    227 # Output: 0.8.22
    228 
    229 # Test CLI installation
    230 npm install -g @bradygaster/squad-cli
    231 squad --version
    232 # Output: 0.8.22
    233 
    234 # Cleanup
    235 cd -
    236 rm -rf /tmp/squad-release-test
    237 ```
    238 
    239 **If installation fails:** npm registry issue or package metadata corruption. DO NOT announce release until this works.
    240 
    241 **Checkpoint:** Both packages install cleanly. Versions match.
    242 
    243 ### Step 7: Sync dev to Next Preview
    244 
    245 After main release, sync dev to the next preview version.
    246 
    247 ```bash
    248 # Checkout dev
    249 git checkout dev
    250 git pull origin dev
    251 
    252 # Bump to next preview version (e.g., 0.8.23-preview.1)
    253 NEXT_VERSION="0.8.23-preview.1"
    254 
    255 # Validate semver
    256 node -p "require('semver').valid('$NEXT_VERSION')"
    257 # Must output the version string, NOT null
    258 
    259 # Update all 3 package.json files
    260 npm version $NEXT_VERSION --workspaces --include-workspace-root --no-git-tag-version
    261 
    262 # Commit
    263 git add package.json packages/squad-sdk/package.json packages/squad-cli/package.json
    264 git commit -m "chore: bump dev to $NEXT_VERSION
    265 
    266 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
    267 
    268 # Push
    269 git push origin dev
    270 ```
    271 
    272 **Checkpoint:** dev branch now shows next preview version. Future dev builds will publish to `@preview` dist-tag.
    273 
    274 ---
    275 
    276 ## Manual Publish (Fallback)
    277 
    278 If `publish.yml` workflow fails or needs to be bypassed, use `workflow_dispatch` to manually trigger publish.
    279 
    280 ```bash
    281 # Trigger manual publish
    282 gh workflow run publish.yml -f version="0.8.22"
    283 
    284 # Monitor the run
    285 gh run watch
    286 ```
    287 
    288 **Rule:** Only use this if automated publish failed. Always investigate why automation failed and fix it for next release.
    289 
    290 ---
    291 
    292 ## Rollback Procedure
    293 
    294 If a release is broken and needs to be rolled back:
    295 
    296 ### 1. Unpublish from npm (Nuclear Option)
    297 
    298 **WARNING:** npm unpublish is time-limited (24 hours) and leaves the version slot burned. Only use if version is critically broken.
    299 
    300 ```bash
    301 # Unpublish (requires npm owner privileges)
    302 npm unpublish @bradygaster/squad-sdk@0.8.22
    303 npm unpublish @bradygaster/squad-cli@0.8.22
    304 ```
    305 
    306 ### 2. Deprecate on npm (Preferred)
    307 
    308 **Preferred approach:** Mark version as deprecated, publish a hotfix.
    309 
    310 ```bash
    311 # Deprecate broken version
    312 npm deprecate @bradygaster/squad-sdk@0.8.22 "Broken release, use 0.8.22.1 instead"
    313 npm deprecate @bradygaster/squad-cli@0.8.22 "Broken release, use 0.8.22.1 instead"
    314 
    315 # Publish hotfix version
    316 # (Follow this runbook with version 0.8.22.1)
    317 ```
    318 
    319 ### 3. Delete GitHub Release and Tag
    320 
    321 ```bash
    322 # Delete GitHub Release
    323 gh release delete "v0.8.22" --yes
    324 
    325 # Delete tag locally and remotely
    326 git tag -d "v0.8.22"
    327 git push origin --delete "v0.8.22"
    328 ```
    329 
    330 ### 4. Revert Commit on main
    331 
    332 ```bash
    333 # Revert version bump commit
    334 git checkout main
    335 git revert HEAD
    336 git push origin main
    337 ```
    338 
    339 **Checkpoint:** Tag and release deleted. main branch reverted. npm packages deprecated or unpublished.
    340 
    341 ---
    342 
    343 ## Common Failure Modes
    344 
    345 ### EOTP Error (npm OTP Required)
    346 
    347 **Symptom:** Workflow fails with `EOTP` error.  
    348 **Root cause:** NPM_TOKEN is a User token with 2FA enabled. CI can't provide OTP.  
    349 **Fix:** Replace NPM_TOKEN with an Automation token (no 2FA). See "NPM_TOKEN Verification" above.
    350 
    351 ### Verify Step 404 (npm Propagation Delay)
    352 
    353 **Symptom:** Verify step fails with 404 even though publish succeeded.  
    354 **Root cause:** npm registry propagation delay (5-30 seconds).  
    355 **Fix:** Verify step now has retry loop (5 attempts, 15s interval). Should auto-resolve. If not, wait 2 minutes and re-run workflow.
    356 
    357 ### Version Mismatch (package.json ≠ tag)
    358 
    359 **Symptom:** Verify step fails with "Package version (X) does not match target version (Y)".  
    360 **Root cause:** package.json version doesn't match the tag version.  
    361 **Fix:** Ensure all 3 package.json files were updated in Step 1. Re-run `npm version` if needed.
    362 
    363 ### 4-Part Version Mangled by npm
    364 
    365 **Symptom:** Published version on npm doesn't match package.json (e.g., 0.8.21.4 became 0.8.2-1.4).  
    366 **Root cause:** 4-part versions are NOT valid semver. npm's parser misinterprets them.  
    367 **Fix:** NEVER use 4-part versions. Only 3-part (0.8.22) or prerelease (0.8.23-preview.1). Run `semver.valid()` before ANY commit.
    368 
    369 ### Draft Release Didn't Trigger Workflow
    370 
    371 **Symptom:** Release created but `publish.yml` never ran.  
    372 **Root cause:** Release was created as a draft. Draft releases don't emit `release: published` event.  
    373 **Fix:** Edit release and change to published: `gh release edit "v$VERSION" --draft=false`. Workflow should trigger immediately.
    374 
    375 ---
    376 
    377 ## Validation Checklist
    378 
    379 Before starting ANY release, confirm:
    380 
    381 - [ ] Version is valid semver: `node -p "require('semver').valid('VERSION')"` returns the version string (NOT null)
    382 - [ ] NPM_TOKEN is an Automation token (no 2FA): `npm token list` shows `read-write` without OTP requirement
    383 - [ ] Branch is clean: `git status` shows "nothing to commit, working tree clean"
    384 - [ ] Tag doesn't exist: `git tag -l "vVERSION"` returns empty
    385 - [ ] `SKIP_BUILD_BUMP=1` is set: `echo $SKIP_BUILD_BUMP` returns `1`
    386 
    387 Before creating GitHub Release:
    388 
    389 - [ ] All 3 package.json files have matching versions: `grep '"version"' package.json packages/*/package.json`
    390 - [ ] Commit is pushed: `git log origin/main..main` returns empty
    391 - [ ] Tag is pushed: `git ls-remote --tags origin vVERSION` returns the tag SHA
    392 
    393 After GitHub Release:
    394 
    395 - [ ] Release is published (NOT draft): `gh release view "vVERSION"` output doesn't contain "(draft)"
    396 - [ ] Workflow is running: `gh run list --workflow=publish.yml --limit 1` shows "in_progress"
    397 
    398 After workflow completes:
    399 
    400 - [ ] Both jobs succeeded: Workflow shows green checkmarks
    401 - [ ] SDK on npm: `npm view @bradygaster/squad-sdk version` returns correct version
    402 - [ ] CLI on npm: `npm view @bradygaster/squad-cli version` returns correct version
    403 - [ ] `latest` tags correct: `npm dist-tag ls @bradygaster/squad-sdk` shows `latest: VERSION`
    404 - [ ] Packages install: `npm install @bradygaster/squad-cli` succeeds
    405 
    406 After dev sync:
    407 
    408 - [ ] dev branch has next preview version: `git show dev:package.json | grep version` shows next preview
    409 
    410 ---
    411 
    412 ## Post-Mortem Reference
    413 
    414 This skill was created after the v0.8.22 release disaster. Full retrospective: `.squad/decisions/inbox/keaton-v0822-retrospective.md`
    415 
    416 **Key learnings:**
    417 1. No release without a runbook = improvisation = disaster
    418 2. Semver validation is mandatory — 4-part versions break npm
    419 3. NPM_TOKEN type matters — User tokens with 2FA fail in CI
    420 4. Draft releases are a footgun — they don't trigger automation
    421 5. Retry logic is essential — npm propagation takes time
    422 
    423 **Never again.**