gowalk-cicd 1.0.160 → 1.0.161
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/action/.daemux-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.161
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.161
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.161
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -76,12 +76,14 @@ inferred safe from a custom step name. Candidate misses never wait or reserve a
|
|
|
76
76
|
|
|
77
77
|
Separate custom workflows remain app-owned. Recognized native dependency jobs
|
|
78
78
|
receive optional lock/toolchain-keyed cache restore/save inside their existing job.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
An app-owned workflow whose push trigger is a plain `branches` list admitting `task/**`
|
|
80
|
+
validates each candidate on that push, which runs on the exact head: the installer deletes its
|
|
81
|
+
duplicate `pull_request` trigger, and a trailing `!task/**` written by earlier releases, in one
|
|
82
|
+
write. Job names, commands and custom checks are unchanged. A push with `branches-ignore`,
|
|
83
|
+
`paths` or `paths-ignore`, or one that does not admit `task/**`, is left as it is; such
|
|
84
|
+
workflows retain separate push/PR concurrency groups, so neither check cancels the other.
|
|
85
|
+
An upgrade also repairs the shared group emitted by 1.0.142–143. Separate platforms and
|
|
86
|
+
repositories keep their existing parallelism.
|
|
85
87
|
|
|
86
88
|
`.gowalk-cicd.lock.json` records the template and generated-file digests. Commit it
|
|
87
89
|
with the configuration and rendered workflows. It is migration state, not a CI job.
|
package/package.json
CHANGED
|
@@ -1,56 +1,38 @@
|
|
|
1
|
-
//
|
|
2
|
-
import { execFileSync } from 'node:child_process';
|
|
1
|
+
// A task/** push already validates the exact candidate head, so a duplicate PR trigger is deleted.
|
|
3
2
|
const REF = '${{ github.ref }}';
|
|
4
3
|
const COALESCED = '${{ github.event.pull_request.head.repo.full_name == github.repository'
|
|
5
4
|
+ ' && github.event.pull_request.head.ref || github.ref_name }}';
|
|
5
|
+
const FACTORY_EXCLUSION = '!task/**';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
// Repair the shared push/PR group emitted by 1.0.142–143.
|
|
8
|
+
function normalizeGroup(doc, concurrency) {
|
|
9
|
+
if (concurrency?.['cancel-in-progress'] !== true || typeof concurrency.group !== 'string') return false;
|
|
10
|
+
const group = concurrency.group.replace(COALESCED, REF);
|
|
11
|
+
const recognized = group.includes('${{ github.workflow }}') || group === `flutter-ci-${REF}`;
|
|
12
|
+
if (group === concurrency.group || !group.includes(REF) || !recognized) return false;
|
|
13
|
+
doc.setIn(['concurrency', 'group'], group);
|
|
14
|
+
return true;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return
|
|
17
|
+
// Only a plain branch list whose last pattern for task refs admits them all; anything else is left alone.
|
|
18
|
+
function candidateBranches(push) {
|
|
19
|
+
if (!push || typeof push !== 'object' || Array.isArray(push)) return null;
|
|
20
|
+
if (['branches-ignore', 'paths', 'paths-ignore'].some(key => Object.hasOwn(push, key))) return null;
|
|
21
|
+
const values = push.branches;
|
|
22
|
+
if (!Array.isArray(values) || values.some(value => typeof value !== 'string')) return null;
|
|
23
|
+
const branches = values.at(-1) === FACTORY_EXCLUSION ? values.slice(0, -1) : values;
|
|
24
|
+
const admitted = branches.findLastIndex(value => value === 'task/**' || value === '**');
|
|
25
|
+
if (admitted < 0 || branches.slice(admitted + 1).some(value => value.startsWith('!'))) return null;
|
|
26
|
+
return branches;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
function
|
|
28
|
-
if (push !== null && (typeof push !== 'object' || Array.isArray(push))) return false;
|
|
29
|
-
const filters = push || {};
|
|
30
|
-
const field = Object.hasOwn(filters, 'branches') ? 'branches' : 'branches-ignore';
|
|
31
|
-
if (!Object.hasOwn(filters, field) && ('tags' in filters || 'tags-ignore' in filters)) return false;
|
|
32
|
-
const values = filters[field] || [];
|
|
33
|
-
if (!Array.isArray(values) || values.some(value => typeof value !== 'string')) return false;
|
|
34
|
-
if ('branches' in filters && 'branches-ignore' in filters) return false;
|
|
35
|
-
const exclusion = field === 'branches' ? '!task/**' : 'task/**';
|
|
36
|
-
if (values.at(-1) === exclusion) return false;
|
|
37
|
-
doc.setIn(['on', 'push'], doc.createNode({ ...filters, [field]: [...values, exclusion] }));
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function upgradeEvents(doc, value, branch) {
|
|
29
|
+
export function upgradeEvents(doc, value) {
|
|
42
30
|
const events = value.on;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
let changed = group !== original;
|
|
51
|
-
if (changed) doc.setIn(['concurrency', 'group'], group);
|
|
52
|
-
if (coversCandidates(events.pull_request, branch, value.jobs)) {
|
|
53
|
-
changed = excludeFactoryPush(doc, events.push) || changed;
|
|
54
|
-
}
|
|
55
|
-
return changed;
|
|
31
|
+
if (!events || !Object.hasOwn(events, 'push') || !Object.hasOwn(events, 'pull_request')) return false;
|
|
32
|
+
const grouped = normalizeGroup(doc, value.concurrency);
|
|
33
|
+
const branches = candidateBranches(events.push);
|
|
34
|
+
if (!branches) return grouped;
|
|
35
|
+
if (branches.length < events.push.branches.length) doc.deleteIn(['on', 'push', 'branches', branches.length]);
|
|
36
|
+
doc.deleteIn(['on', 'pull_request']);
|
|
37
|
+
return true;
|
|
56
38
|
}
|
|
@@ -3,7 +3,7 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { readYaml, MigrationRepair } from './yaml.mjs';
|
|
5
5
|
import { upgradeReuse } from './validation-reuse.mjs';
|
|
6
|
-
import {
|
|
6
|
+
import { upgradeEvents } from './validation-events.mjs';
|
|
7
7
|
const CACHE = 'caa296126883cff596d87d8935842f9db880ef25';
|
|
8
8
|
const PREFIX = '.github/actions/swift-app/scripts/';
|
|
9
9
|
|
|
@@ -54,12 +54,10 @@ export function planValidation(root, managed) {
|
|
|
54
54
|
if (!existsSync(directory)) return [];
|
|
55
55
|
const writes = [];
|
|
56
56
|
const files = readdirSync(directory).filter(file => /\.ya?ml$/.test(file) && !managed.includes(file));
|
|
57
|
-
// Another app-owned workflow may depend on this workflow's push evidence.
|
|
58
|
-
const branch = files.length === 1 ? defaultBranch(root) : '';
|
|
59
57
|
for (const file of files) {
|
|
60
58
|
const source = readFileSync(join(directory, file), 'utf8');
|
|
61
59
|
const { doc, value } = readYaml(source, file);
|
|
62
|
-
const events = upgradeEvents(doc, value
|
|
60
|
+
const events = upgradeEvents(doc, value);
|
|
63
61
|
const reused = upgradeReuse(doc, value, file);
|
|
64
62
|
const cached = upgradeCaches(doc, doc.toJS({ maxAliasCount: 100 }), file);
|
|
65
63
|
if (cached || events || reused) {
|