Files
Neil 126d8046a9 fix: harden post-merge review findings and close CI gaps (#145)
Follow-ups to the #126/#133/#135 merges, from the review of each.

From #135 (draft attachments):
- upload.ts: completedFileIds compacted its result with .filter() while the
  caller indexed it positionally against the staged list. If Slack omitted an
  id for any file but the last, every subsequent id shifted up a slot and the
  wrong file was attached to the draft. Ids are now positionally aligned with
  undefined holes preserved, and the response is only trusted when its length
  matches what was sent.
- message-draft-actions.ts: cleanupOrphanedDraftFiles takes an input object,
  matching the codebase convention and clearing the new max-params warning.
- drafts.ts: correct ensureDraftOk's comment — both transports already throw
  on ok:false, so it is defence-in-depth, not the load-bearing guard it
  claimed to be.
- Reformat the files the PR left failing oxfmt.

From #126 (wrapped error causes):
- String() on a cause is not total: a null-prototype object threw inside the
  CLI's own catch handlers, turning a printable error into a crash. Route all
  stringification through safeString().
- Cap the cause walk at 8 levels so a long chain cannot emit a multi-hundred-
  kilobyte single-line message.
- Collapse a cause that merely restates its parent ("fetch failed: fetch
  failed").

Docs (AGENTS.md requires SKILL.md track the code):
- README/SKILL.md/llms.txt document --attach on draft create/update, including
  update's merge-into-existing semantics.
- README: note --no-unfurl works with --schedule, which was implemented and
  tested in #133 but left out of the flag list.

CI:
- Run typecheck and format:check. Neither ran anywhere, so a type error or
  formatting drift could reach main — #135 arrived with oxfmt already failing.
- Trigger on push to main. CI was pull_request-only, so the merge commits main
  is actually built from were never validated.
- Gate the release workflow on typecheck too.
2026-09-01 23:33:53 -07:00

83 lines
2.2 KiB
YAML

name: Release
on:
push:
tags:
- "v*"
jobs:
release:
name: Build + Release
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write # npm provenance
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Detect release type
id: meta
run: |
TAG="${GITHUB_REF_NAME}"
if [[ "$TAG" == *"-rc."* ]]; then
echo "prerelease=true" >> "$GITHUB_OUTPUT"
echo "npm_tag=rc" >> "$GITHUB_OUTPUT"
else
echo "prerelease=false" >> "$GITHUB_OUTPUT"
echo "npm_tag=latest" >> "$GITHUB_OUTPUT"
fi
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: package.json
registry-url: "https://registry.npmjs.org"
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Install rcodesign (for macOS binary signing from Linux)
run: |
set -euo pipefail
# Install cargo-binstall for fast pre-built binary downloads
curl -L --proto '=https' --tlsv1.2 -sSf \
https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
# Install rcodesign (from apple-codesign crate) via pre-built binary
cargo binstall --no-confirm apple-codesign
rcodesign --version
- name: Lint
run: bun run lint
- name: Typecheck
run: bun run typecheck
- name: Test
run: bun run test
- name: Build release binaries
run: bun run build:release
- name: Upload release assets
uses: softprops/action-gh-release@v2
with:
files: |
release/agent-slack-*
release/checksums-sha256.txt
generate_release_notes: true
prerelease: ${{ steps.meta.outputs.prerelease == 'true' }}
- name: Build for npm
run: bun run build:npm
- name: Publish to npm
run: npm publish --provenance --access public --tag ${{ steps.meta.outputs.npm_tag }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}