yadflow 2.4.1 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -2
- package/cli/doctor.mjs +34 -0
- package/package.json +1 -1
- package/skills/yad-checks/SKILL.md +7 -0
- package/skills/yad-checks/templates/gitlab/yad-checks.gitlab-ci.yml +8 -0
- package/skills/yad-checks/templates/gitlab/yad-verified-commits.gitlab-ci.yml +5 -0
- package/skills/yad-hub-bridge/SKILL.md +8 -0
- package/skills/yad-hub-bridge/templates/gitlab/yad-gate-sync.gitlab-ci.yml +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
## [2.4.
|
|
1
|
+
## [2.4.2](https://github.com/abdelrahmannasr/yadflow/compare/v2.4.1...v2.4.2) (2026-06-14)
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
### Bug Fixes
|
|
5
5
|
|
|
6
|
-
*
|
|
6
|
+
* route GitLab CI gate jobs to tag-locked runners via $YAD_RUNNER_TAGS ([a0311c5](https://github.com/abdelrahmannasr/yadflow/commit/a0311c5af647f63968f3f34e8e6e6fa48b7423d8)), closes [#50](https://github.com/abdelrahmannasr/yadflow/issues/50)
|
|
7
7
|
|
|
8
8
|
# [2.2.0](https://github.com/abdelrahmannasr/yadflow/compare/v2.1.0...v2.2.0) (2026-06-14)
|
|
9
9
|
|
package/cli/doctor.mjs
CHANGED
|
@@ -162,9 +162,43 @@ export function projectChecks(checks, root) {
|
|
|
162
162
|
}
|
|
163
163
|
if (!registry.repos.length) check(checks, 'repos', 'project', 'warn', 'no code repos registered', 'run `yad setup` to connect one');
|
|
164
164
|
}
|
|
165
|
+
|
|
166
|
+
ciTagsChecks(checks, root, hub, registry);
|
|
165
167
|
return { hub, registry };
|
|
166
168
|
}
|
|
167
169
|
|
|
170
|
+
// GitLab CI runner tags: the wired fragments run docker-image jobs. On instances whose runners are
|
|
171
|
+
// all tag-locked (run_untagged: false), an untagged image job matches no runner and sits `pending`
|
|
172
|
+
// forever — silently blocking the gates (issue #50). A current fragment carries
|
|
173
|
+
// `tags: [$YAD_RUNNER_TAGS]`; warn on any wired GitLab fragment that sets an `image:` but has no
|
|
174
|
+
// `tags:` (an old install, or one hand-reverted by a sync). Pure local read — no API calls.
|
|
175
|
+
export function ciTagsChecks(checks, root, hub, registry) {
|
|
176
|
+
const untagged = (p) => {
|
|
177
|
+
try {
|
|
178
|
+
const txt = fs.readFileSync(p, 'utf8');
|
|
179
|
+
return /^\s*image:/m.test(txt) && !/^\s*tags:/m.test(txt);
|
|
180
|
+
} catch { return false; } // absent fragment is not this check's concern
|
|
181
|
+
};
|
|
182
|
+
const fragments = [];
|
|
183
|
+
if (hub?.platform === 'gitlab' && (hub.bridge_enabled === true || hub.bridge === true)) {
|
|
184
|
+
fragments.push(
|
|
185
|
+
{ scope: 'hub', file: '.gitlab/ci/yad-gate-sync.yml', path: path.join(root, '.gitlab/ci/yad-gate-sync.yml') },
|
|
186
|
+
{ scope: 'hub', file: '.gitlab/ci/yad-verified-commits.yml', path: path.join(root, '.gitlab/ci/yad-verified-commits.yml') },
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
for (const repo of registry?.repos || []) {
|
|
190
|
+
if (repo.platform !== 'gitlab' || !repo.path) continue;
|
|
191
|
+
fragments.push({ scope: repo.name, file: '.gitlab/ci/yad-checks.yml', path: path.join(path.resolve(root, repo.path), '.gitlab/ci/yad-checks.yml') });
|
|
192
|
+
}
|
|
193
|
+
for (const f of fragments) {
|
|
194
|
+
if (untagged(f.path)) {
|
|
195
|
+
check(checks, `ci-tags:${f.scope}`, 'project', 'warn',
|
|
196
|
+
`${f.scope}: ${f.file} runs a docker job with no \`tags:\` [YAD-CI-001]`,
|
|
197
|
+
'tag-locked runners (run_untagged: false) will strand it at `pending` — run `yad update`, then set the `YAD_RUNNER_TAGS` CI/CD variable');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
168
202
|
export function epicChecks(checks, root) {
|
|
169
203
|
const epicsDir = path.join(root, 'epics');
|
|
170
204
|
if (!exists(epicsDir)) return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yadflow",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"description": "Yadflow — the gated, team, multi-repo SDLC: author → review → build with a PR-driven review gate and a zero-dependency `yad` CLI (setup, gate, commit, open-pr, repo). A BMAD module + 22 yad-* skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "AbdelRahman Nasr",
|
|
@@ -88,6 +88,13 @@ Copy from this skill's `templates/`:
|
|
|
88
88
|
human to paste (graceful degradation — never guess-edit a pipeline you cannot parse).
|
|
89
89
|
- The legacy standalone `templates/gitlab/.gitlab-ci.yml` is retained only for a clean greenfield repo
|
|
90
90
|
that prefers a single self-contained file; the include path above is the default.
|
|
91
|
+
- **Tag-locked runners** (`run_untagged: false`, common on self-hosted): the fragment's jobs run a
|
|
92
|
+
docker image, so set a `YAD_RUNNER_TAGS` CI/CD variable (e.g. `dind_runner`) to route them — the
|
|
93
|
+
`default:` block emits `tags: [$YAD_RUNNER_TAGS]`. When unset, current GitLab (≥15) drops the
|
|
94
|
+
empty-expanded tag so the jobs run untagged (gitlab.com shared runners); older versions may
|
|
95
|
+
strand them `pending`, in which case set the variable to a real tag. The variable lives in
|
|
96
|
+
project settings, so it survives every `yad` sync. Single value only — `tags: [$VAR]` is one tag
|
|
97
|
+
equal to the whole variable, not a comma-split.
|
|
91
98
|
|
|
92
99
|
- Ensure `<repo>/package.json` defines `lint`, `build`, `test` scripts (see `references/check-gates.md`
|
|
93
100
|
for the canonical scripts). **Only ADD a missing script; never overwrite an existing one.**
|
|
@@ -11,6 +11,14 @@
|
|
|
11
11
|
# colliding with the host project's own job names.
|
|
12
12
|
default:
|
|
13
13
|
image: node:20
|
|
14
|
+
# Runner selection. These jobs need a docker/dind executor; on instances whose runners are all
|
|
15
|
+
# tag-locked (run_untagged: false) an untagged image job never starts. Set the YAD_RUNNER_TAGS
|
|
16
|
+
# CI/CD variable (Settings → CI/CD → Variables, e.g. `dind_runner`) to route them — it lives in
|
|
17
|
+
# project settings, so it survives every `yad` sync. When unset, current GitLab (>=15) drops the
|
|
18
|
+
# empty-expanded tag so the job runs untagged (gitlab.com shared runners); some older versions
|
|
19
|
+
# instead strand it `pending` — if so, set the variable to a real tag. Single value only:
|
|
20
|
+
# `tags: [$VAR]` is one tag equal to the whole variable, not a comma-split.
|
|
21
|
+
tags: [$YAD_RUNNER_TAGS]
|
|
14
22
|
|
|
15
23
|
.sdlc_mr_only:
|
|
16
24
|
rules:
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
# Job name is yad-hub-prefixed so it can coexist with the code-repo fragment in one pipeline.
|
|
13
13
|
yad-hub-verified-commits:
|
|
14
14
|
needs: []
|
|
15
|
+
# Runner selection: set the YAD_RUNNER_TAGS CI/CD variable (e.g. `dind_runner`) to route this
|
|
16
|
+
# docker job on instances whose runners are tag-locked (run_untagged: false) — it lives in
|
|
17
|
+
# project Settings → CI/CD → Variables, so it survives every `yad` sync. When unset, current
|
|
18
|
+
# GitLab (>=15) runs the job untagged; older versions may strand it — set a real tag if so.
|
|
19
|
+
tags: [$YAD_RUNNER_TAGS]
|
|
15
20
|
image: node:20
|
|
16
21
|
variables:
|
|
17
22
|
GIT_DEPTH: "0" # full history so the gate can diff against the target branch
|
|
@@ -89,6 +89,14 @@ remains valid and is the fallback whenever CI cannot push.
|
|
|
89
89
|
`SDLC_GATE_TOKEN` project-access-token variable (`read_api` + `write_repository`). GitLab fires no
|
|
90
90
|
pipeline on an approval alone, so the schedule is the path that picks approvals up (≤ ~15 min
|
|
91
91
|
latency); MR events and the merge are near-immediate.
|
|
92
|
+
- **If your runners are tag-locked** (`run_untagged: false`, common on self-hosted): set a
|
|
93
|
+
`YAD_RUNNER_TAGS` CI/CD variable (e.g. `dind_runner`) so the docker-image `yad-gate-sync` job
|
|
94
|
+
is routed to a runner — otherwise it sits `pending` forever. The fragment emits
|
|
95
|
+
`tags: [$YAD_RUNNER_TAGS]`. When unset, current GitLab (≥15) drops the empty-expanded tag so the
|
|
96
|
+
job runs untagged (gitlab.com shared runners); older versions may strand it `pending`, in which
|
|
97
|
+
case set the variable to a real tag. The variable lives in project settings, so it survives
|
|
98
|
+
every `yad` sync. Single value only — `tags: [$VAR]` is one tag equal to the whole variable,
|
|
99
|
+
not a comma-split.
|
|
92
100
|
3. Commit the workflow to the hub. GitHub needs nothing else — the ephemeral `github.token` reads the
|
|
93
101
|
PR and pushes the ledger. If the default branch is protected, see the workflow header for the
|
|
94
102
|
bypass / PAT options; until then the run fails visibly and manual `yad gate sync` still works.
|
|
@@ -31,6 +31,11 @@ variables:
|
|
|
31
31
|
|
|
32
32
|
yad-gate-sync:
|
|
33
33
|
needs: []
|
|
34
|
+
# Runner selection: set the YAD_RUNNER_TAGS CI/CD variable (e.g. `dind_runner`) to route this
|
|
35
|
+
# docker job on instances whose runners are tag-locked (run_untagged: false) — it lives in
|
|
36
|
+
# project Settings → CI/CD → Variables, so it survives every `yad` sync. When unset, current
|
|
37
|
+
# GitLab (>=15) runs the job untagged; older versions may strand it — set a real tag if so.
|
|
38
|
+
tags: [$YAD_RUNNER_TAGS]
|
|
34
39
|
image: node:20
|
|
35
40
|
rules:
|
|
36
41
|
# MR-event path: fires on MR open / push to the review branch — NOT on approval (see header).
|