Skip to content

CI and automation

This page is the single map of every automated pipeline in the lastcall repository. Human contributors and Cursor agents should start here when asking “what runs when?” or “why did this workflow fail?”.

Related deep-dives:

Overview

mermaid
flowchart TB
  subgraph merge_gate["Merge gate (every push / PR)"]
    CI["CI — lint, test, build, docs, audit, pack, bundle size"]
    BUN["Bun compatibility — test + build"]
    CODEQL["CodeQL — security analysis"]
    LABEL["Labeler — PR labels"]
  end

  subgraph deploy["Deploy (push to main)"]
    DOCS["Docs — VitePress → GitHub Pages"]
  end

  subgraph release["Release (tag v*)"]
    PUB["Publish — npm OIDC + GitHub Release"]
  end

  subgraph weekly["Weekly (Monday UTC)"]
    DEP["Dependabot 06:00 — opens grouped PRs"]
    CQL["CodeQL 06:00 — scheduled scan"]
  end

Workflow reference

WorkflowFileTriggerBlocks merge?Purpose
CIci.ymlPush / PR to main / master, manualYesFull quality gate + build + docs + npm pack --dry-run + bundle size
Bunci.yml (bun job)Same as CIYesnpm test + npm run build under Bun runtime
Docsdocs.ymlPush to main / master, manualAdvisoryVitePress build → GitHub Pages
CodeQLcodeql.ymlPush / PR / schedule / manualAdvisoryStatic security analysis (TypeScript)
Labelerlabeler.ymlPR opened / syncNoAuto-labels (ci, tests, documentation, …)
Publishpublish.ymlPush tag v*, manualN/A (release)npm OIDC publish + GitHub Release from CHANGELOG

Dependabot (dependabot.yml) is not a workflow but opens grouped PRs weekly (Monday 06:00 UTC). Those PRs must pass CI and Bun.

CI (merge gate)

File: .github/workflows/ci.yml
Node: 22 (test toolchain; published library targets Node 18+ via tsup)
npm: 11.4.2 (matches packageManager in package.json)
Concurrency: one run per ref; PRs cancel in-progress runs.

StepCommandWhat it proves
Installnpm ciReproducible lockfile
Quality gatenpm run ciLint, Prettier, tsc, Vitest coverage (100% lines), npm audit
Librarynpm run builddist/ ESM + CJS + .d.ts via tsup
Documentationnpm run docs:buildVitePress links and MD valid
Package tarballnpm pack --dry-runnpm publish surface = dist + README + LICENSE
Bundle sizegzip -c dist/index.jsESM bundle ≤ 15 KB gzipped (README advertises a lean package)

Local equivalent

bash
npm run ci
npm run build
npm run docs:build
npm pack --dry-run

npm run ci is the canonical pre-commit command — same steps as the CI quality gate. Docs and build are separate locally (mirrors Actions: CI workflow runs them after npm run ci).

Bun compatibility job

lastcall documents Bun support (docs/guides/bun.md). A separate bun job installs deps with npm ci, then runs npm test and npm run build with Bun available on the runner. This is lighter than duplicating the full matrix — merge gate stays one Node 22 job like shieldkit, with Bun as an extra runtime check specific to this library.

Why not Node 18 in CI? Runtime target is Node 18+ (engines, tsup target node18), but Vitest 4 / Rolldown requires Node 20.12+ for the test toolchain. Consumers on Node 18 run the compiled dist/; CI validates the toolchain on Node 22.

Docs (GitHub Pages)

File: .github/workflows/docs.yml
Trigger: push to main / master (not PRs — avoids deploying unmerged docs).
Intentionally skips re-running the full CI gate — relies on branch protection requiring green CI before merge.

CodeQL

File: .github/workflows/codeql.yml

TypeScript analysis on src/ with the security-and-quality query pack. build-mode: none — no compile step required. Results appear in the GitHub Security tab. Runs on push, pull requests, weekly (Mondays 06:00 UTC), and workflow_dispatch.

Free for public repositories.

Dependabot

.github/dependabot.yml opens weekly grouped PRs with labels dependencies and automated.

GroupPatterns
testingvitest*, @vitest/*
typescript-and-buildtypescript, tsup, tsx, esbuild
linting-and-formattingeslint*, @eslint/*, prettier*, typescript-eslint*
docsvitepress
security-updates* (security advisories only)

@types/node semver-major updates are ignored — major tracks Node major; CI uses Node 22.

Labels

.github/labeler.yml applies PR labels via pull_request_target:

LabelPaths
ci.github/**
dependenciespackage.json, package-lock.json
documentationdocs/, website/, *.md, SECURITY.md
codesrc/**
teststest/**, **/*.test.ts
examplesexamples/**
cursor.cursor/**
securitySECURITY.md, core shutdown modules in src/

Publishing

Preferred: merge to main, tag vX.Y.Z, push — Publish workflow uses npm trusted publishing (OIDC, no NPM_TOKEN).

  1. Merge release PR with dated CHANGELOG section and version bump
  2. git tag vX.Y.Z && git push origin vX.Y.Z (tag must match package.json)
  3. Workflow runs npm run cibuildnpm pack --dry-runnpm publish → GitHub Release from CHANGELOG

Full setup (trusted publisher, first publish bootstrap): npm publishing.

Cursor automation

Agent skills and rules live in .cursor/ and are documented in Cursor skills. They are tracked in git (unlike .cursor/plans/).

PolicyFile
Pre-commit gate.cursor/rules/pre-commit-quality-gate.mdc
Release / CHANGELOG.cursor/rules/lastcall-release-changelog.mdc
CI commands.cursor/skills/lastcall-pre-commit-ci/SKILL.md
End-to-end release.cursor/skills/lastcall-ship-release/SKILL.md

Comparison with sibling repos

Patternshieldkit (ai-shield)lastcallbanal (site)
CI shapeSingle Node 22 jobNode 22 job + Bun jobSingle Node 22 job
npm run cilint → test → auditlint → coverage → auditlint → test → audit
PublishOIDC + tag v*SameN/A (no npm)
Extra workflowsAI SDK compat, Red TeamBundle size gateverify-tools weekly
Issue templatesNoneBug + feature YAMLNone

lastcall intentionally omits shieldkit’s AI SDK Compatibility and Red Team workflows — zero production dependencies, no live-model security surface. It adds Bun and bundle size checks because those are documented product promises.