Repository navigation
135 lines (119 loc) · 6.27 KB
/
Copy pathvalidate.yml
File metadata and controls
135 lines (119 loc) · 6.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# THIS NAME IS AN INTERFACE, NOT A LABEL. `release-cli-nightly.yml` triggers on
# `workflow_run: workflows: [Validate]`, which matches this string and not this
# file's path — a nightly is only published from a commit this workflow passed
# on. Rename it and the nightly stops firing permanently, with no error
# anywhere and nothing turning red. Rename both together, or neither.
name: Validate
on:
push:
branches: [main]
# No `branches:` filter, deliberately. Lint, typecheck, and tests have no
# interest in where a PR eventually merges, and filtering on `main` silently
# skipped this workflow on stacked PRs.
#
# The filter matches the PR's base ref, but GitHub also resolves a stacked
# PR's *eventual* target and matches on that — so `branches: [main]` did run
# on PRs based on another branch, until it stopped. Measured on the
# #71→#93→#94→#95→#100→#102→#103→#106 stack: every PR up to #102 got a
# `Validate` run, while #103 and #106 got none, across 16 `pull_request`
# events that other workflows handled fine. A filter that works for six PRs
# and quietly fails on the seventh is worse than one that never worked,
# because nobody re-checks it.
#
# `ready_for_review` is NOT in the default set (opened/synchronize/reopened)
# and must be named: without it a draft marked ready gets no fresh run until
# something happens to push again, which is exactly the state #103 sat in.
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: read
# This workflow runs the CLI this repository builds. Its telemetry is the same
# production client a user's install has, so every invocation here would count
# as adoption. Opting out is the CLI's own switch, read by the built binary.
env:
TASKLESS_TELEMETRY_DISABLED: "1"
jobs:
validate:
name: Validate
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install pnpm
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: .nvmrc
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Lint
run: pnpm lint
- name: Typecheck
run: pnpm typecheck
- name: Build
run: pnpm build
- name: Test
run: pnpm test
# `test:scripts` covers .github/scripts/ AND the skill scripts under
# .agents/skills/*/scripts/, which are zero-dependency CommonJS with
# node:test suites beside them. It lives in package.json so the same
# command runs locally.
#
# Its globs are UNQUOTED on purpose. Node's own glob expansion exits 0
# when a pattern matches nothing, so a renamed or moved directory would
# report a clean pass having run no tests at all; an unmatched shell glob
# reaches node as a literal path and fails loudly with "Could not find".
# An absent check reads like a passing one, so take the loud failure.
- name: Test workflow and skill scripts
run: pnpm test:scripts
# House style, enforced rather than documented. The rules live in
# `.taskless/` and are scoped to the documents people and agents actually
# read: every README, CLAUDE.md, `.conventions/*.md`, this directory's
# workflows, and comments under `packages/cli/src/`.
#
# A step here, not a standalone `taskless.yml`. The canonical recipe
# (`taskless agent ci`) writes a separate workflow so that onboarding
# never touches a pipeline it does not own, but the two things this repo
# needs are only available inside this job. Branch protection requires
# `Validate` and nothing else, so a separate workflow would report and
# block nothing, which is the whole of what #104 asked for; and `check`
# runs this repo's own build, which the `Build` step above has already
# produced. Full scan rather than the recipe's diff scan, for the reason
# `Validate specs` gives below: rot accumulates in the files a PR does
# not touch, and the scoped corpus is small enough that a diff scan buys
# nothing.
#
# Placed after the test steps rather than immediately after `Build`, so
# that the existing signal order (lint, types, build, tests) stays intact
# for anyone used to reading these logs. It only needs to be after
# `Build`; nothing above it depends on it.
#
# `pnpm cli` is the workspace build, NOT a published release. That is a
# deliberate divergence from `ci.txt` and is ENFORCED, not requested:
# the `ci-uses-workspace-cli` rule fails this very workflow if the
# invocation is changed back, and carries the reasoning in its `note:`.
# `Build` above ran `pnpm build` on this same commit, so `dist/` here
# can be neither stale nor missing, and an absent `dist/` would fail
# this step loudly rather than pass it empty.
#
# This blocks. `check` exits non-zero on any error-severity finding and
# on an engine that failed or timed out, so an em dash added to a covered
# document turns the build red. Warning-severity rules report without
# failing, which is what `severity: warning` in a rule means.
#
# No authentication and no secrets: static rules (Vale and ast-grep) run
# unauthenticated. Runtime rules under `.taskless/rules/runtime/` are
# skipped without a token; that directory is empty today, and wiring
# `TASKLESS_TOKEN` is the separate decision to make when it is not.
- name: Check house style
run: pnpm cli check
# Repo-wide, not changed-files-only: spec rot accumulates in the specs a
# PR does not touch, so a scoped check would never surface it.
- name: Validate specs
run: pnpm openspec validate --all --strict
# `--strict` validates what the parser read, not that it read the whole
# file. A second `##` inside `## Requirements` ends the section and every
# requirement below it becomes invisible — valid, unread, and green.
- name: Check spec requirement visibility
run: node .github/scripts/openspec-visibility.cjs