forgedock 1.17.0 → 1.19.0
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/bin/engine/outcome-codes.mjs +37 -2
- package/bin/engine/phases.mjs +207 -106
- package/bin/engine/runlog.mjs +17 -2
- package/bin/engine/telemetry-seam.mjs +3 -0
- package/bin/engine/telemetry.test.mjs +3 -2
- package/bin/engine-cli.mjs +37 -2
- package/bin/engine.mjs +221 -15
- package/bin/forgedock.mjs +1 -1
- package/bin/hooks/pre-tool-use.mjs +65 -32
- package/bin/runner.mjs +125 -6
- package/bin/stats/aggregate.mjs +7 -3
- package/bin/stats/cache.mjs +7 -3
- package/bin/stats/github-source.mjs +203 -24
- package/bin/stats/index.mjs +46 -9
- package/bin/stats/render.mjs +1 -1
- package/bin/stats/stats.test.mjs +264 -15
- package/commands/cleanup.md +10 -3
- package/commands/deploy-pr.md +64 -0
- package/commands/fix-ci.md +20 -6
- package/commands/milestone.md +34 -17
- package/commands/orchestrate/phase-4-execution.md +11 -4
- package/commands/review-pr-staging.md +145 -522
- package/commands/review-pr.md +496 -3124
- package/commands/test-gate.md +25 -10
- package/commands/work-on/build/architect.md +66 -1
- package/commands/work-on/build/implement.md +21 -1
- package/commands/work-on/build/validate.md +322 -28
- package/commands/work-on/build.md +173 -95
- package/commands/work-on/close.md +50 -15
- package/commands/work-on/decompose.md +72 -34
- package/commands/work-on/investigate.md +16 -12
- package/commands/work-on/remediate.md +58 -25
- package/commands/work-on/review.md +36 -21
- package/commands/work-on.md +1 -2
- package/docs/CONFIG.md +132 -26
- package/docs/OUTCOME-CODES.md +12 -3
- package/docs/RELEASE-NOTES.md +12 -0
- package/docs/STATS.md +13 -5
- package/docs/TELEMETRY.md +7 -4
- package/docs/WORK-ON-RUNTIME.md +24 -0
- package/docs/spec/forge-protocol-v1.md +2 -2
- package/package.json +2 -2
- package/packages/protocol/src/phases.js +5 -5
- package/packages/protocol/src/types.js +1 -1
- package/scripts/acceptance-red-green.sh +90 -0
- package/scripts/acceptance-red-green.test.sh +74 -0
- package/scripts/cap-findings.sh +1 -1
- package/scripts/cap-findings.test.sh +3 -1
- package/scripts/check-contract-scope.test.sh +2 -0
- package/scripts/check-edge-cases.sh +143 -0
- package/scripts/check-edge-cases.test.sh +175 -0
- package/scripts/check-spec-bash.sh +5 -1
- package/scripts/check-spec-bash.test.sh +20 -0
- package/scripts/check-spec-markers.sh +2 -0
- package/scripts/check-test-tmp-cleanup.sh +56 -0
- package/scripts/check-test-tmp-cleanup.test.sh +69 -0
- package/scripts/ci-local/adapters/azure-pipelines.mjs +113 -0
- package/scripts/ci-local/adapters/bitbucket.mjs +64 -0
- package/scripts/ci-local/adapters/buildkite.mjs +58 -0
- package/scripts/ci-local/adapters/circleci.mjs +101 -0
- package/scripts/ci-local/adapters/common.mjs +115 -0
- package/scripts/ci-local/adapters/explicit.mjs +21 -0
- package/scripts/ci-local/adapters/github-actions.mjs +349 -0
- package/scripts/ci-local/adapters/gitlab-ci.mjs +184 -0
- package/scripts/ci-local/adapters/portability.mjs +104 -0
- package/scripts/ci-local/adapters/task-runners.mjs +67 -0
- package/scripts/ci-local/cli.mjs +50 -0
- package/scripts/ci-local/lib.mjs +371 -0
- package/scripts/ci-local/plan.mjs +186 -0
- package/scripts/ci-local/run.mjs +345 -0
- package/scripts/ci-local/scoping.mjs +508 -0
- package/scripts/ci-local.sh +97 -0
- package/scripts/ci-local.test.sh +919 -0
- package/scripts/classify-finding.sh +32 -6
- package/scripts/classify-finding.test.sh +23 -0
- package/scripts/classify-test-run.sh +69 -0
- package/scripts/classify-test-run.test.sh +90 -0
- package/scripts/close-parent-c3.test.sh +71 -0
- package/scripts/consumer-sweep.sh +569 -0
- package/scripts/consumer-sweep.test.sh +357 -0
- package/scripts/detect-append-registries.sh +106 -0
- package/scripts/detect-append-registries.test.sh +64 -0
- package/scripts/diff-size.sh +93 -4
- package/scripts/diff-size.test.sh +59 -2
- package/scripts/fixtures/ci-local/azure/azure-pipelines.yml +11 -0
- package/scripts/fixtures/ci-local/bitbucket/bitbucket-pipelines.yml +12 -0
- package/scripts/fixtures/ci-local/buildkite/.buildkite/pipeline.yml +10 -0
- package/scripts/fixtures/ci-local/circleci/.circleci/config.yml +29 -0
- package/scripts/fixtures/ci-local/gha-basic/.github/workflows/ci.yml +59 -0
- package/scripts/fixtures/ci-local/gha-basic/.github/workflows/docs.yml +10 -0
- package/scripts/fixtures/ci-local/gha-basic/.github/workflows/nightly.yml +10 -0
- package/scripts/fixtures/ci-local/gha-basic/docs/index.md +1 -0
- package/scripts/fixtures/ci-local/gha-basic/src/greet.sh +2 -0
- package/scripts/fixtures/ci-local/gha-basic/tests/greet.test.sh +3 -0
- package/scripts/fixtures/ci-local/gha-dorny/.github/workflows/ci.yml +51 -0
- package/scripts/fixtures/ci-local/gha-dorny/backend/app.py +1 -0
- package/scripts/fixtures/ci-local/gha-dorny/docs/a.md +1 -0
- package/scripts/fixtures/ci-local/gha-dorny/frontend/app.js +1 -0
- package/scripts/fixtures/ci-local/gha-run/.github/workflows/ci.yml +39 -0
- package/scripts/fixtures/ci-local/gha-run/src/x.txt +1 -0
- package/scripts/fixtures/ci-local/gitlab/.gitlab-ci.yml +43 -0
- package/scripts/fixtures/ci-local/gitlab/docs/d.md +1 -0
- package/scripts/fixtures/ci-local/gitlab/src/a.txt +1 -0
- package/scripts/fixtures/ci-local/monorepo/.github/workflows/ci.yml +13 -0
- package/scripts/fixtures/ci-local/monorepo/package-lock.json +1 -0
- package/scripts/fixtures/ci-local/monorepo/packages/a/src/a.sh +2 -0
- package/scripts/fixtures/ci-local/monorepo/packages/a/tests/a.test.sh +3 -0
- package/scripts/fixtures/ci-local/monorepo/packages/b/src/b.sh +2 -0
- package/scripts/fixtures/ci-local/monorepo/packages/b/tests/b.test.sh +3 -0
- package/scripts/fixtures/ci-local/no-ci/Makefile +6 -0
- package/scripts/fixtures/ci-local/no-ci/package.json +1 -0
- package/scripts/fixtures/ci-local/no-ci/src/a.js +1 -0
- package/scripts/fixtures/ci-local/no-ci/src/b.js +1 -0
- package/scripts/fixtures/ci-local/no-ci/tests/a.test.js +2 -0
- package/scripts/fixtures/ci-local/no-ci/tests/b.test.js +2 -0
- package/scripts/forge-root.test.sh +14 -12
- package/scripts/lib/telemetry.sh +1 -0
- package/scripts/publish-staging-sync.test.sh +48 -0
- package/scripts/remediate-approved-head.test.sh +2 -0
- package/scripts/remediate-basesync.test.sh +1 -1
- package/scripts/resolve-deploy-gate.sh +32 -6
- package/scripts/resolve-deploy-gate.test.sh +42 -1
- package/scripts/review-acceptance-gate.sh +2 -2
- package/scripts/review-acceptance-gate.test.sh +20 -0
- package/scripts/review-delta.sh +8 -1
- package/scripts/review-delta.test.sh +19 -0
- package/scripts/review-finalize.sh +1579 -0
- package/scripts/review-finalize.test.sh +1040 -0
- package/scripts/review-pr-delta-wiring.test.sh +32 -72
- package/scripts/review-pr-domain-map.test.sh +18 -13
- package/scripts/review-pr-gate2.test.sh +9 -65
- package/scripts/review-pr-staging-scope.test.sh +14 -98
- package/scripts/review-prepare.sh +53 -15
- package/scripts/review-prepare.test.sh +37 -3
- package/scripts/review-roster.sh +16 -2
- package/scripts/review-roster.test.sh +22 -0
- package/scripts/run-shell-tests.sh +5 -0
- package/scripts/telemetry.test.sh +2 -0
- package/scripts/trusted-comments.test.sh +11 -3
- package/scripts/verify-phase-trail.test.sh +8 -0
- package/scripts/wait-ci-green.sh +61 -9
- package/scripts/wait-ci-green.test.sh +44 -6
- package/scripts/with-run-tmpdir.sh +20 -0
package/scripts/diff-size.sh
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# diff-size.sh — the ONE measurement of a build's diff size
|
|
2
|
+
# diff-size.sh — the ONE measurement of a build's diff size and scope (forge#3450, forge#3862).
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios
|
|
4
4
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
5
|
#
|
|
6
6
|
# Usage: diff-size.sh --repo-path P --base B [--threshold N] [--exclude-glob G]...
|
|
7
|
+
# [--test-weight PCT] [--module-depth N] [--plan-files FILE] [--estimate N] [--overrun-pct PCT]
|
|
8
|
+
# The size is never a gate (forge#3862): review_weight scales review depth and the scope diff (--plan-files) flags
|
|
9
|
+
# files outside the architect plan. --threshold/over/cohesive are DEPRECATED (kept one release for old callers).
|
|
7
10
|
# Measures lines changed (added + deleted) by the index plus any earlier commits against the MERGE BASE of
|
|
8
11
|
# HEAD and origin/B (git diff --cached --numstat --no-renames $(git merge-base HEAD origin/B)), so commits that
|
|
9
12
|
# landed on the base after the branch point are never counted as this build's changes. Exit 2 when the merge
|
|
@@ -15,7 +18,7 @@
|
|
|
15
18
|
# build/ dist/ generated/ fixtures/ vendor/ are anchored to the repo root (so first-party dirs such as
|
|
16
19
|
# commands/work-on/build/ are counted); __generated__/ and __snapshots__/ match at any depth.
|
|
17
20
|
# Globs are data, never evaluated.
|
|
18
|
-
# Default globs (mirrored in docs/CONFIG.md under build.diff_size.exclude_globs):
|
|
21
|
+
# Default globs (mirrored in docs/CONFIG.md under build.scope.exclude_globs, deprecated alias build.diff_size.exclude_globs):
|
|
19
22
|
# lockfiles (package-lock.json yarn.lock pnpm-lock.yaml Cargo.lock poetry.lock uv.lock go.sum Gemfile.lock
|
|
20
23
|
# composer.lock), *.min.*, *.snap, root-anchored dist/ build/ generated/ fixtures/ vendor/, any-depth
|
|
21
24
|
# __generated__/ __snapshots__/
|
|
@@ -27,6 +30,17 @@
|
|
|
27
30
|
# by basename); cohesive_lines = the union (a new test file counts once). cohesive=true when diff_lines>0 and
|
|
28
31
|
# cohesive_lines*100 >= 70*diff_lines and diff_lines <= threshold*3/2 (integer math; threshold 0 -> false).
|
|
29
32
|
# Test lines are classified, never discounted from diff_lines.
|
|
33
|
+
# review_weight (forge#3862): ws_lines = lines changed with whitespace ignored (git diff -w; a pure re-indent is 0)
|
|
34
|
+
# over the counted (non-excluded) files; review_weight = ceil((ws_lines of non-test files + --test-weight percent
|
|
35
|
+
# (default 50) of ws_lines of test files)); modules = distinct directories (first --module-depth path segments,
|
|
36
|
+
# default 2) holding a file with at least one non-whitespace changed line. Keys ws_lines, review_weight, modules
|
|
37
|
+
# follow cohesive= and precede top=.
|
|
38
|
+
# Scope diff, emitted only with --plan-files and/or --estimate: --plan-files FILE lists the architect's planned files
|
|
39
|
+
# (one per line; a leading "- " or "* ", backticks and "./" are stripped; an entry ending in "/" is a directory prefix;
|
|
40
|
+
# blank and "#" lines are ignored). scope=no_baseline (no entries) | ok | out_of_plan; plan_files=N; out_of_plan_count=K;
|
|
41
|
+
# up to 50 "out_of_plan=<path>" lines (counted files absent from the plan). --estimate N with --overrun-pct P
|
|
42
|
+
# (default 200) sets overrun=true when ws_lines*100 > N*P (N=0 means no estimate: overrun=false). Unreadable
|
|
43
|
+
# --plan-files is exit 2 (fail closed: an unreadable plan is never "in plan").
|
|
30
44
|
# Exit: 0 measured (even when over); 2 usage or git failure with EMPTY stdout (fail closed: unknown is not zero).
|
|
31
45
|
|
|
32
46
|
set -euo pipefail
|
|
@@ -34,7 +48,7 @@ set -euo pipefail
|
|
|
34
48
|
_TEL="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/telemetry.sh"; [ -f "$_TEL" ] && . "$_TEL" 2>/dev/null
|
|
35
49
|
type forge_emit >/dev/null 2>&1 || forge_emit() { :; }
|
|
36
50
|
|
|
37
|
-
REPO_PATH=""; BASE=""; THRESHOLD="1000"; EXTRA=()
|
|
51
|
+
REPO_PATH=""; BASE=""; THRESHOLD="1000"; EXTRA=(); TEST_WEIGHT="50"; MODULE_DEPTH="2"; PLAN_FILE=""; ESTIMATE=""; OVERRUN_PCT="200"
|
|
38
52
|
die() { echo "diff-size.sh: $*" >&2; exit 2; }
|
|
39
53
|
while [ $# -gt 0 ]; do
|
|
40
54
|
case "$1" in
|
|
@@ -42,12 +56,33 @@ while [ $# -gt 0 ]; do
|
|
|
42
56
|
--base) [ $# -ge 2 ] || die "missing value for $1"; BASE="$2"; shift 2 ;;
|
|
43
57
|
--threshold) [ $# -ge 2 ] || die "missing value for $1"; THRESHOLD="$2"; shift 2 ;;
|
|
44
58
|
--exclude-glob) [ $# -ge 2 ] || die "missing value for $1"; [ -z "$2" ] || EXTRA+=("$2"); shift 2 ;;
|
|
59
|
+
--test-weight) [ $# -ge 2 ] || die "missing value for $1"; TEST_WEIGHT="$2"; shift 2 ;;
|
|
60
|
+
--module-depth) [ $# -ge 2 ] || die "missing value for $1"; MODULE_DEPTH="$2"; shift 2 ;;
|
|
61
|
+
--plan-files) [ $# -ge 2 ] || die "missing value for $1"; PLAN_FILE="$2"; shift 2 ;;
|
|
62
|
+
--estimate) [ $# -ge 2 ] || die "missing value for $1"; ESTIMATE="$2"; shift 2 ;;
|
|
63
|
+
--overrun-pct) [ $# -ge 2 ] || die "missing value for $1"; OVERRUN_PCT="$2"; shift 2 ;;
|
|
45
64
|
*) die "unknown argument: $1" ;;
|
|
46
65
|
esac
|
|
47
66
|
done
|
|
48
67
|
[ -n "$REPO_PATH" ] && [ -d "$REPO_PATH" ] || die "--repo-path must be an existing directory"
|
|
49
68
|
[ -n "$BASE" ] || die "--base is required"
|
|
50
69
|
case "$THRESHOLD" in ""|*[!0-9]*) die "--threshold must be a non-negative integer" ;; esac
|
|
70
|
+
case "$TEST_WEIGHT" in ""|*[!0-9]*) die "--test-weight must be a non-negative integer percent" ;; esac
|
|
71
|
+
case "$MODULE_DEPTH" in ""|0|*[!0-9]*) die "--module-depth must be a positive integer" ;; esac
|
|
72
|
+
case "$OVERRUN_PCT" in ""|*[!0-9]*) die "--overrun-pct must be a non-negative integer percent" ;; esac
|
|
73
|
+
case "$ESTIMATE" in ""|*[!0-9]*) [ -z "$ESTIMATE" ] || die "--estimate must be a non-negative integer" ;; esac
|
|
74
|
+
PLAN=(); PLAN_SET=0
|
|
75
|
+
if [ -n "$PLAN_FILE" ]; then
|
|
76
|
+
[ -f "$PLAN_FILE" ] && [ -r "$PLAN_FILE" ] || die "--plan-files must be a readable file"
|
|
77
|
+
PLAN_SET=1
|
|
78
|
+
while IFS= read -r _l || [ -n "$_l" ]; do
|
|
79
|
+
_l="${_l#"${_l%%[![:space:]]*}"}"; _l="${_l%"${_l##*[![:space:]]}"}"
|
|
80
|
+
case "$_l" in ""|"#"*) continue ;; esac
|
|
81
|
+
case "$_l" in "- "*|"* "*) _l="${_l#??}" ;; esac
|
|
82
|
+
_l="${_l//\`/}"; _l="${_l#./}"
|
|
83
|
+
[ -n "$_l" ] && PLAN+=("$_l")
|
|
84
|
+
done < "$PLAN_FILE"
|
|
85
|
+
fi
|
|
51
86
|
|
|
52
87
|
DEFAULTS=(package-lock.json yarn.lock pnpm-lock.yaml Cargo.lock poetry.lock uv.lock go.sum Gemfile.lock composer.lock
|
|
53
88
|
'*.min.*' '*.snap' __generated__/ __snapshots__/)
|
|
@@ -102,6 +137,32 @@ while IFS= read -r -d $'\001' rec; do
|
|
|
102
137
|
fi
|
|
103
138
|
done <<< "$RAW"
|
|
104
139
|
|
|
140
|
+
# Whitespace-insensitive pass (forge#3862): review_weight and module count come from `git diff -w`.
|
|
141
|
+
RAWW="$(git -C "$REPO_PATH" diff --cached -w --numstat --no-renames -z "$MB" -- | tr '\0' '\001')" \
|
|
142
|
+
|| die "git diff -w against merge base $MB failed"
|
|
143
|
+
WSL=0; WS_NT=0; WS_T=0; MODS=$'\001'; NMODS=0
|
|
144
|
+
while IFS= read -r -d $'\001' rec; do
|
|
145
|
+
[ -n "$rec" ] || continue
|
|
146
|
+
a="${rec%%$'\t'*}"; rest="${rec#*$'\t'}"; d="${rest%%$'\t'*}"; path="${rest#*$'\t'}"
|
|
147
|
+
case "$a" in ''|*[!0-9]*) a=0 ;; esac
|
|
148
|
+
case "$d" in ''|*[!0-9]*) d=0 ;; esac
|
|
149
|
+
n=$((a + d))
|
|
150
|
+
excluded "$path" && continue
|
|
151
|
+
WSL=$((WSL + n))
|
|
152
|
+
if is_test "$path"; then WS_T=$((WS_T + n)); else WS_NT=$((WS_NT + n)); fi
|
|
153
|
+
if [ "$n" -gt 0 ]; then
|
|
154
|
+
dir="${path%/*}"; [ "$dir" = "$path" ] && dir="."
|
|
155
|
+
mod=""; _i=0; _rest="$dir"
|
|
156
|
+
while [ "$_i" -lt "$MODULE_DEPTH" ] && [ -n "$_rest" ]; do
|
|
157
|
+
_seg="${_rest%%/*}"; mod="${mod:+$mod/}$_seg"
|
|
158
|
+
case "$_rest" in */*) _rest="${_rest#*/}" ;; *) _rest="" ;; esac
|
|
159
|
+
_i=$((_i + 1))
|
|
160
|
+
done
|
|
161
|
+
case "$MODS" in *$'\001'"$mod"$'\001'*) ;; *) MODS="${MODS}${mod}"$'\001'; NMODS=$((NMODS + 1)) ;; esac
|
|
162
|
+
fi
|
|
163
|
+
done <<< "$RAWW"
|
|
164
|
+
REVIEW_WEIGHT=$(( (WS_NT * 100 + WS_T * TEST_WEIGHT + 99) / 100 ))
|
|
165
|
+
|
|
105
166
|
OVER=false
|
|
106
167
|
if [ "$THRESHOLD" -gt 0 ] && [ "$TOTAL" -gt "$THRESHOLD" ]; then OVER=true; fi
|
|
107
168
|
echo "diff_lines=$TOTAL"
|
|
@@ -115,8 +176,36 @@ echo "new_lines=$NEWL"
|
|
|
115
176
|
echo "test_lines=$TESTL"
|
|
116
177
|
echo "cohesive_lines=$COHL"
|
|
117
178
|
echo "cohesive=$COHESIVE"
|
|
179
|
+
echo "ws_lines=$WSL"
|
|
180
|
+
echo "review_weight=$REVIEW_WEIGHT"
|
|
181
|
+
echo "modules=$NMODS"
|
|
182
|
+
OOP_LIST=""; OOP=0; SCOPE=ok
|
|
183
|
+
if [ "$PLAN_SET" = 1 ] || [ -n "$ESTIMATE" ]; then
|
|
184
|
+
if [ "${#PLAN[@]}" -eq 0 ]; then SCOPE=no_baseline; else
|
|
185
|
+
while IFS= read -r -d $'\001' rec; do
|
|
186
|
+
[ -n "$rec" ] || continue
|
|
187
|
+
path="${rec#*$'\t'}"; path="${path#*$'\t'}"
|
|
188
|
+
excluded "$path" && continue
|
|
189
|
+
inplan=0
|
|
190
|
+
for _p in "${PLAN[@]}"; do
|
|
191
|
+
case "$_p" in */) case "$path" in "$_p"*) inplan=1; break ;; esac ;; *) [ "$path" = "$_p" ] && { inplan=1; break; } ;; esac
|
|
192
|
+
done
|
|
193
|
+
if [ "$inplan" = 0 ]; then OOP=$((OOP + 1)); OOP_LIST="${OOP_LIST}${path}"$'\n'; fi
|
|
194
|
+
done <<< "$RAW"
|
|
195
|
+
[ "$OOP" -gt 0 ] && SCOPE=out_of_plan
|
|
196
|
+
fi
|
|
197
|
+
OVERRUN=false
|
|
198
|
+
if [ -n "$ESTIMATE" ] && [ "$ESTIMATE" -gt 0 ] && [ $((WSL * 100)) -gt $((ESTIMATE * OVERRUN_PCT)) ]; then OVERRUN=true; fi
|
|
199
|
+
echo "scope=$SCOPE"
|
|
200
|
+
echo "plan_files=${#PLAN[@]}"
|
|
201
|
+
echo "out_of_plan_count=$OOP"
|
|
202
|
+
[ -n "$ESTIMATE" ] && { echo "estimate=$ESTIMATE"; echo "overrun=$OVERRUN"; }
|
|
203
|
+
fi
|
|
118
204
|
_res=OK; if [ "$COHESIVE" = true ]; then _res=COHESIVE; elif [ "$OVER" = true ]; then _res=OVER; fi
|
|
119
|
-
forge_emit diff_size lines="$TOTAL" excluded="$EXCL" threshold="$THRESHOLD" result="$_res"
|
|
205
|
+
forge_emit diff_size lines="$TOTAL" excluded="$EXCL" threshold="$THRESHOLD" result="$_res" review_weight="$REVIEW_WEIGHT" modules="$NMODS" ws_lines="$WSL"
|
|
120
206
|
if [ -n "$LIST" ]; then
|
|
121
207
|
printf '%s' "$LIST" | sort -t' ' -k1,1nr | head -n 10 | sed 's/^/top=/' || true
|
|
122
208
|
fi
|
|
209
|
+
if [ -n "$OOP_LIST" ]; then
|
|
210
|
+
printf '%s' "$OOP_LIST" | head -n 50 | sed 's/^/out_of_plan=/' || true
|
|
211
|
+
fi
|
|
@@ -137,10 +137,67 @@ check "test name patterns" "$OUT" test_lines 30
|
|
|
137
137
|
reset; gen 20 > keep.py; gen 900 > package-lock.json; git add -A
|
|
138
138
|
OUT="$(run --threshold 1000)"; check "excluded not in new_lines" "$OUT" new_lines 20
|
|
139
139
|
|
|
140
|
-
# existing key order is unchanged: cohesion keys sit between over= and top=
|
|
140
|
+
# existing key order is unchanged: cohesion keys sit between over= and top=; review keys follow cohesive=
|
|
141
141
|
reset; gen 3 > s.txt; git add -A
|
|
142
142
|
KEYS="$(run | sed -n 's/^\([a-z_]*\)=.*/\1/p' | tr '\n' ' ')"
|
|
143
|
-
[ "$KEYS" = "diff_lines excluded_lines threshold over new_lines test_lines cohesive_lines cohesive top " ] && ok || bad "key order ($KEYS)"
|
|
143
|
+
[ "$KEYS" = "diff_lines excluded_lines threshold over new_lines test_lines cohesive_lines cohesive ws_lines review_weight modules top " ] && ok || bad "key order ($KEYS)"
|
|
144
|
+
|
|
145
|
+
# review_weight (forge#3862): a pure re-indent counts about 0, whatever its raw size
|
|
146
|
+
reset; mkdir -p svc; awk 'BEGIN{for(i=0;i<120;i++) print "if x:\n y" i}' > svc/h.py; git add -A; git commit -qm h; git push -q origin feat:staging 2>/dev/null
|
|
147
|
+
awk 'BEGIN{for(i=0;i<120;i++) print "if x:\n y" i}' > svc/h.py; git add -A
|
|
148
|
+
OUT="$(run)"; check "re-indent raw diff_lines" "$OUT" diff_lines 240; check "re-indent ws_lines" "$OUT" ws_lines 0
|
|
149
|
+
check "re-indent review_weight" "$OUT" review_weight 0; check "re-indent modules" "$OUT" modules 0
|
|
150
|
+
git reset -q --hard origin/staging
|
|
151
|
+
|
|
152
|
+
# tests are weighted (default 50%, configurable); ws_lines is unweighted
|
|
153
|
+
reset; mkdir -p src tests; gen 100 > src/m.py; gen 200 > tests/test_m.py; git add -A
|
|
154
|
+
OUT="$(run)"; check "weight ws_lines" "$OUT" ws_lines 300; check "weight default 50" "$OUT" review_weight 200
|
|
155
|
+
OUT="$(run --test-weight 25)"; check "weight 25" "$OUT" review_weight 150
|
|
156
|
+
OUT="$(run --test-weight 0)"; check "weight 0" "$OUT" review_weight 100
|
|
157
|
+
OUT="$(run --test-weight 100)"; check "weight 100" "$OUT" review_weight 300
|
|
158
|
+
reset; mkdir -p src; gen 3 > src/o.py; mkdir -p tests; gen 1 > tests/test_o.py; git add -A
|
|
159
|
+
OUT="$(run)"; check "weight rounds up" "$OUT" review_weight 4
|
|
160
|
+
|
|
161
|
+
# generated and vendored code is excluded from review_weight and modules
|
|
162
|
+
reset; gen 10 > keep.py; mkdir -p vendor generated; gen 900 > vendor/v.js; gen 900 > generated/g.js; gen 900 > package-lock.json; git add -A
|
|
163
|
+
OUT="$(run)"; check "excluded ws_lines" "$OUT" ws_lines 10; check "excluded review_weight" "$OUT" review_weight 10; check "excluded modules" "$OUT" modules 1
|
|
164
|
+
|
|
165
|
+
# module count: distinct directories at --module-depth
|
|
166
|
+
reset; mkdir -p a/b/c a/b/d a/e f; gen 5 > a/b/c/1.py; gen 5 > a/b/d/2.py; gen 5 > a/e/3.py; gen 5 > f/4.py; gen 5 > root.py; git add -A
|
|
167
|
+
OUT="$(run)"; check "modules depth 2" "$OUT" modules 4
|
|
168
|
+
OUT="$(run --module-depth 1)"; check "modules depth 1" "$OUT" modules 3
|
|
169
|
+
OUT="$(run --module-depth 3)"; check "modules depth 3" "$OUT" modules 5
|
|
170
|
+
|
|
171
|
+
# scope diff: in-plan, out-of-plan, prefix entries, formatting noise, no baseline, overrun
|
|
172
|
+
reset; mkdir -p src tests docs; gen 10 > src/a.py; gen 10 > src/b.py; gen 10 > tests/test_a.py; gen 10 > docs/x.md; git add -A
|
|
173
|
+
printf '%s\n' '# plan' '- `src/a.py`' '* ./src/b.py' '' 'tests/' > "$TMP/plan"
|
|
174
|
+
OUT="$(run --plan-files "$TMP/plan")"
|
|
175
|
+
check "scope out_of_plan" "$OUT" scope out_of_plan; check "scope count" "$OUT" out_of_plan_count 1
|
|
176
|
+
check "scope plan_files" "$OUT" plan_files 3; check "scope path" "$OUT" out_of_plan docs/x.md
|
|
177
|
+
printf '%s\n' src/a.py src/b.py tests/test_a.py docs/x.md > "$TMP/plan"
|
|
178
|
+
OUT="$(run --plan-files "$TMP/plan")"; check "scope ok" "$OUT" scope ok; check "scope ok count" "$OUT" out_of_plan_count 0
|
|
179
|
+
printf '%s\n' 'src/a.py' > "$TMP/plan"
|
|
180
|
+
OUT="$(run --plan-files "$TMP/plan")"; check "scope 3 out" "$OUT" out_of_plan_count 3
|
|
181
|
+
: > "$TMP/plan"; OUT="$(run --plan-files "$TMP/plan")"; check "empty plan is no_baseline" "$OUT" scope no_baseline; check "no_baseline count" "$OUT" out_of_plan_count 0
|
|
182
|
+
OUT="$(run)"; [ -z "$(val "$OUT" scope)" ] && ok || bad "scope keys absent without plan args"
|
|
183
|
+
# excluded files are never out-of-plan; a path is data (glob chars, spaces) not a pattern
|
|
184
|
+
reset; mkdir -p vendor; gen 5 > vendor/z.js; gen 5 > 'we ird[1].txt'; git add -A
|
|
185
|
+
printf '%s\n' 'src/a.py' > "$TMP/plan"
|
|
186
|
+
OUT="$(run --plan-files "$TMP/plan")"; check "excluded not out-of-plan" "$OUT" out_of_plan_count 1; check "path with space and glob quoted" "$OUT" out_of_plan 'we ird[1].txt'
|
|
187
|
+
printf '%s\n' '*.txt' > "$TMP/plan"; OUT="$(run --plan-files "$TMP/plan")"; check "plan entry is not a glob" "$OUT" out_of_plan_count 1
|
|
188
|
+
# overrun against the plan estimate (ws-insensitive actual)
|
|
189
|
+
reset; gen 500 > big.py; git add -A
|
|
190
|
+
OUT="$(run --estimate 200)"; check "overrun 2.5x" "$OUT" overrun true; check "overrun estimate" "$OUT" estimate 200; check "overrun no plan file is no_baseline" "$OUT" scope no_baseline
|
|
191
|
+
OUT="$(run --estimate 250)"; check "at 2x not overrun" "$OUT" overrun false
|
|
192
|
+
OUT="$(run --estimate 200 --overrun-pct 300)"; check "custom overrun pct" "$OUT" overrun false
|
|
193
|
+
OUT="$(run --estimate 0)"; check "estimate 0 is no estimate" "$OUT" overrun false
|
|
194
|
+
# unreadable plan fails closed; bad numeric args are usage errors
|
|
195
|
+
OUT="$(bash "$S" --repo-path "$TMP/w" --base staging --plan-files "$TMP/none" 2>/dev/null)"; rc=$?
|
|
196
|
+
{ [ "$rc" = 2 ] && [ -z "$OUT" ]; } && ok || bad "unreadable plan (rc=$rc)"
|
|
197
|
+
for bad_arg in "--test-weight x" "--module-depth 0" "--overrun-pct -1" "--estimate x"; do
|
|
198
|
+
OUT="$(bash "$S" --repo-path "$TMP/w" --base staging $bad_arg 2>/dev/null)"; rc=$?
|
|
199
|
+
{ [ "$rc" = 2 ] && [ -z "$OUT" ]; } && ok || bad "bad arg $bad_arg (rc=$rc)"
|
|
200
|
+
done
|
|
144
201
|
|
|
145
202
|
# fail closed: bad repo path, bad base, bad threshold, unknown arg, missing base
|
|
146
203
|
OUT="$(bash "$S" --repo-path "$TMP/nope" --base staging 2>/dev/null)"; rc=$?
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
version: 2.1
|
|
2
|
+
jobs:
|
|
3
|
+
test:
|
|
4
|
+
docker:
|
|
5
|
+
- image: cimg/base:stable
|
|
6
|
+
steps:
|
|
7
|
+
- checkout
|
|
8
|
+
- run:
|
|
9
|
+
name: unit
|
|
10
|
+
command: echo circle-unit
|
|
11
|
+
secured:
|
|
12
|
+
docker:
|
|
13
|
+
- image: cimg/base:stable
|
|
14
|
+
steps:
|
|
15
|
+
- run: echo secured
|
|
16
|
+
deploy-prod:
|
|
17
|
+
docker:
|
|
18
|
+
- image: cimg/base:stable
|
|
19
|
+
steps:
|
|
20
|
+
- run: echo deploy
|
|
21
|
+
workflows:
|
|
22
|
+
main:
|
|
23
|
+
jobs:
|
|
24
|
+
- test
|
|
25
|
+
- secured:
|
|
26
|
+
context: org-secrets
|
|
27
|
+
requires: [test]
|
|
28
|
+
- deploy-prod:
|
|
29
|
+
requires: [test]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
branches: [main]
|
|
5
|
+
paths:
|
|
6
|
+
- 'src/**'
|
|
7
|
+
- 'tests/**'
|
|
8
|
+
- '.github/workflows/ci.yml'
|
|
9
|
+
jobs:
|
|
10
|
+
unit:
|
|
11
|
+
name: Unit
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-node@v4
|
|
16
|
+
with:
|
|
17
|
+
node-version: 20
|
|
18
|
+
- name: unit tests
|
|
19
|
+
run: bash tests/greet.test.sh
|
|
20
|
+
matrix:
|
|
21
|
+
runs-on: ${{ matrix.os }}
|
|
22
|
+
strategy:
|
|
23
|
+
matrix:
|
|
24
|
+
os: [ubuntu-latest, macos-14, windows-latest]
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
- run: echo matrix-ok
|
|
28
|
+
withservice:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
services:
|
|
31
|
+
postgres:
|
|
32
|
+
image: postgres:16
|
|
33
|
+
env:
|
|
34
|
+
POSTGRES_PASSWORD: example
|
|
35
|
+
ports:
|
|
36
|
+
- 5432:5432
|
|
37
|
+
options: --health-cmd pg_isready --health-interval 5s
|
|
38
|
+
steps:
|
|
39
|
+
- run: echo service-ok
|
|
40
|
+
needsecret:
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
env:
|
|
43
|
+
API_TOKEN: ${{ secrets.API_TOKEN }}
|
|
44
|
+
steps:
|
|
45
|
+
- run: echo uses-secret
|
|
46
|
+
unknownaction:
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
steps:
|
|
49
|
+
- uses: some-org/mystery-action@v9
|
|
50
|
+
deployprod:
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
environment: production
|
|
53
|
+
steps:
|
|
54
|
+
- run: echo deploy
|
|
55
|
+
conditional:
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
if: github.event_name == 'push'
|
|
58
|
+
steps:
|
|
59
|
+
- run: echo push-only
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# docs
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
branches: [staging, main]
|
|
5
|
+
jobs:
|
|
6
|
+
changes:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
outputs:
|
|
9
|
+
backend: ${{ steps.filter.outputs.backend }}
|
|
10
|
+
frontend: ${{ steps.filter.outputs.frontend }}
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: dorny/paths-filter@v3
|
|
14
|
+
id: filter
|
|
15
|
+
with:
|
|
16
|
+
filters: |
|
|
17
|
+
backend:
|
|
18
|
+
- 'backend/**'
|
|
19
|
+
frontend:
|
|
20
|
+
- 'frontend/**'
|
|
21
|
+
backend:
|
|
22
|
+
needs: changes
|
|
23
|
+
if: needs.changes.outputs.backend == 'true'
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
services:
|
|
26
|
+
redis:
|
|
27
|
+
image: redis:7
|
|
28
|
+
ports:
|
|
29
|
+
- 6379:6379
|
|
30
|
+
steps:
|
|
31
|
+
- run: echo backend-ok
|
|
32
|
+
frontend:
|
|
33
|
+
needs: changes
|
|
34
|
+
if: needs.changes.outputs.frontend == 'true'
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
steps:
|
|
37
|
+
- run: echo frontend-ok
|
|
38
|
+
integration:
|
|
39
|
+
needs: [changes]
|
|
40
|
+
if: needs.changes.outputs.backend == 'true'
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
env:
|
|
43
|
+
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
|
44
|
+
steps:
|
|
45
|
+
- run: echo integration
|
|
46
|
+
deploy-staging:
|
|
47
|
+
needs: [backend]
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
environment: staging
|
|
50
|
+
steps:
|
|
51
|
+
- run: echo deploy
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
print("a")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# d
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log(1)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
jobs:
|
|
5
|
+
first:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
steps:
|
|
8
|
+
- run: echo first >> "$RUN_LOG"
|
|
9
|
+
- name: reads GITHUB_ENV
|
|
10
|
+
run: |
|
|
11
|
+
echo "FROM_STEP=carried" >> "$GITHUB_ENV"
|
|
12
|
+
- run: test "$FROM_STEP" = carried
|
|
13
|
+
env:
|
|
14
|
+
RUN_LOG: run.log
|
|
15
|
+
second:
|
|
16
|
+
needs: first
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- run: echo second
|
|
20
|
+
failing:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- run: |
|
|
24
|
+
echo "about to fail"
|
|
25
|
+
exit 3
|
|
26
|
+
skippedbyneed:
|
|
27
|
+
needs: failing
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- run: echo never
|
|
31
|
+
slow:
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
timeout-minutes: 1
|
|
34
|
+
steps:
|
|
35
|
+
- run: echo slow-ok
|
|
36
|
+
broken-install:
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
steps:
|
|
39
|
+
- run: npm ci --no-audit --registry=http://127.0.0.1:9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ok
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
stages: [build, test, deploy]
|
|
2
|
+
variables:
|
|
3
|
+
GREETING: hello
|
|
4
|
+
.template:
|
|
5
|
+
script:
|
|
6
|
+
- echo template
|
|
7
|
+
lint:
|
|
8
|
+
stage: test
|
|
9
|
+
image: node:20
|
|
10
|
+
rules:
|
|
11
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
12
|
+
changes:
|
|
13
|
+
- src/**/*
|
|
14
|
+
script:
|
|
15
|
+
- echo "$GREETING lint"
|
|
16
|
+
unit:
|
|
17
|
+
stage: test
|
|
18
|
+
extends: .template
|
|
19
|
+
only:
|
|
20
|
+
- merge_requests
|
|
21
|
+
withdb:
|
|
22
|
+
stage: test
|
|
23
|
+
services:
|
|
24
|
+
- postgres:16
|
|
25
|
+
script:
|
|
26
|
+
- echo db
|
|
27
|
+
manualjob:
|
|
28
|
+
stage: test
|
|
29
|
+
when: manual
|
|
30
|
+
script:
|
|
31
|
+
- echo manual
|
|
32
|
+
release:
|
|
33
|
+
stage: deploy
|
|
34
|
+
environment: production
|
|
35
|
+
script:
|
|
36
|
+
- echo release
|
|
37
|
+
docsonly:
|
|
38
|
+
stage: test
|
|
39
|
+
rules:
|
|
40
|
+
- changes:
|
|
41
|
+
- docs/**/*
|
|
42
|
+
script:
|
|
43
|
+
- echo docs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
jobs:
|
|
5
|
+
test-a:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
steps:
|
|
8
|
+
- run: bash packages/a/tests/a.test.sh
|
|
9
|
+
- run: bash packages/b/tests/b.test.sh
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- run: shellcheck -S error packages/a/src/a.sh packages/b/src/b.sh
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"lockfileVersion":1}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "name": "noci", "version": "1.0.0", "scripts": { "test": "node --test tests/", "lint": "echo lint-ok" } }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = 1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = 2
|