browser-commander 0.16.0 → 0.16.1

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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.16.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 542bf75: Fix CI/CD false positives, false negatives and warnings across all workflows
8
+ - Repair `if:` conditions that started with `!`, which a YAML plain scalar cannot do
9
+ - Replace `always()` with `!cancelled()` so cancelled runs stop propagating
10
+ - Gate `instant-release` and `changeset-pr` on lint and test, so a manual release can no longer publish unvalidated code
11
+ - Make the changelog fragment checks fail instead of only warning
12
+ - Pass `github.base_ref` and free-form `workflow_dispatch` inputs through environment variables instead of interpolating them into shell bodies
13
+ - Update `actions/setup-python` to v6, `codecov/codecov-action` to v7 and `peter-evans/create-pull-request` to v8
14
+ - Extend `scripts/check-ci-workflows.mjs` so each of the above becomes a permanent policy check
15
+ - Add repository-wide secrets scanning and a 1500-line file limit gate
16
+
3
17
  ## 0.16.0
4
18
 
5
19
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-commander",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "description": "Universal browser automation library that supports both Playwright and Puppeteer with a unified API",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -0,0 +1,70 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+
4
+ import { findManualVersionChanges } from '../../../../scripts/check-version-modification.mjs';
5
+
6
+ // The real implementation shells out to git; injecting the diff keeps these
7
+ // cases independent of the branch the suite happens to run on.
8
+ function stubDiff(diffsByPath) {
9
+ return (_baseRef, path) => diffsByPath[path] ?? '';
10
+ }
11
+
12
+ describe('check-version-modification', () => {
13
+ it('reports nothing when no manifest changed', () => {
14
+ assert.deepEqual(findManualVersionChanges('main', stubDiff({})), []);
15
+ });
16
+
17
+ it('detects a hand-edited package.json version', () => {
18
+ const diff = stubDiff({
19
+ 'js/package.json': [
20
+ '--- a/js/package.json',
21
+ '+++ b/js/package.json',
22
+ '- "version": "0.16.0",',
23
+ '+ "version": "0.17.0",',
24
+ ].join('\n'),
25
+ });
26
+
27
+ assert.deepEqual(findManualVersionChanges('main', diff), [
28
+ 'js/package.json',
29
+ ]);
30
+ });
31
+
32
+ it('detects hand-edited pyproject and Cargo versions together', () => {
33
+ const diff = stubDiff({
34
+ 'python/pyproject.toml': '+version = "0.5.4"',
35
+ 'rust/Cargo.toml': '+version = "0.9.1"',
36
+ });
37
+
38
+ assert.deepEqual(findManualVersionChanges('main', diff), [
39
+ 'python/pyproject.toml',
40
+ 'rust/Cargo.toml',
41
+ ]);
42
+ });
43
+
44
+ it('ignores a non-numeric version key', () => {
45
+ // pyproject declares `version = "literal: pyproject.toml: project.version"`
46
+ // for its release tooling; that is not a version bump.
47
+ const diff = stubDiff({
48
+ 'python/pyproject.toml':
49
+ '+version = "literal: pyproject.toml: project.version"',
50
+ });
51
+
52
+ assert.deepEqual(findManualVersionChanges('main', diff), []);
53
+ });
54
+
55
+ it('ignores an unrelated edit to a manifest', () => {
56
+ const diff = stubDiff({
57
+ 'js/package.json': '+ "description": "A new description",',
58
+ });
59
+
60
+ assert.deepEqual(findManualVersionChanges('main', diff), []);
61
+ });
62
+
63
+ it('ignores a removed version line', () => {
64
+ const diff = stubDiff({
65
+ 'js/package.json': '- "version": "0.16.0",',
66
+ });
67
+
68
+ assert.deepEqual(findManualVersionChanges('main', diff), []);
69
+ });
70
+ });
@@ -70,4 +70,157 @@ jobs:
70
70
  console.error = originalError;
71
71
  }
72
72
  });
73
+
74
+ it('rejects untrusted expressions interpolated into run bodies', () => {
75
+ const workflow = `name: Test
76
+ on:
77
+ workflow_dispatch:
78
+ inputs:
79
+ bump_type:
80
+ type: choice
81
+ options:
82
+ - patch
83
+ description:
84
+ type: string
85
+ env:
86
+ GIT_CONFIG_KEY_0: init.defaultBranch
87
+ jobs:
88
+ release:
89
+ runs-on: ubuntu-latest
90
+ timeout-minutes: 5
91
+ concurrency:
92
+ group: \${{ github.workflow }}-\${{ github.ref }}-release
93
+ cancel-in-progress: true
94
+ steps:
95
+ - uses: actions/checkout@v6
96
+ - run: echo "\${{ github.base_ref }}"
97
+ - run: bump "\${{ github.event.inputs.bump_type }}" "\${{ github.event.inputs.description }}"
98
+ - uses: peter-evans/create-pull-request@v7
99
+ with:
100
+ title: 'release \${{ github.event.inputs.description }}'
101
+ `;
102
+ const originalError = console.error;
103
+ console.error = () => {};
104
+
105
+ try {
106
+ withWorkflow(workflow, (filePath) => {
107
+ // One github.base_ref interpolation, one free-form input inside a run
108
+ // body (bump_type is a choice input, and the create-pull-request title
109
+ // is an action input rather than a shell body), one outdated action.
110
+ assert.equal(checkWorkflow(filePath), 3);
111
+ });
112
+ } finally {
113
+ console.error = originalError;
114
+ }
115
+ });
116
+
117
+ it('rejects a condition that starts with the YAML tag indicator', () => {
118
+ const workflow = `name: Test
119
+ on: push
120
+ env:
121
+ GIT_CONFIG_KEY_0: init.defaultBranch
122
+ jobs:
123
+ test:
124
+ runs-on: ubuntu-latest
125
+ timeout-minutes: 5
126
+ concurrency:
127
+ group: \${{ github.workflow }}-\${{ github.ref }}-test
128
+ cancel-in-progress: true
129
+ if: !cancelled() && github.event_name == 'push'
130
+ steps:
131
+ - uses: actions/checkout@v6
132
+ `;
133
+ const originalError = console.error;
134
+ console.error = () => {};
135
+
136
+ try {
137
+ withWorkflow(workflow, (filePath) => {
138
+ assert.equal(checkWorkflow(filePath), 1);
139
+ });
140
+ } finally {
141
+ console.error = originalError;
142
+ }
143
+ });
144
+
145
+ it('rejects outdated setup-python and codecov versions', () => {
146
+ const workflow = `name: Test
147
+ on: push
148
+ env:
149
+ GIT_CONFIG_KEY_0: init.defaultBranch
150
+ jobs:
151
+ test:
152
+ runs-on: ubuntu-latest
153
+ timeout-minutes: 5
154
+ concurrency:
155
+ group: \${{ github.workflow }}-\${{ github.ref }}-test
156
+ cancel-in-progress: true
157
+ steps:
158
+ - uses: actions/checkout@v6
159
+ - uses: actions/setup-python@v5
160
+ - uses: codecov/codecov-action@v6
161
+ `;
162
+ const originalError = console.error;
163
+ console.error = () => {};
164
+
165
+ try {
166
+ withWorkflow(workflow, (filePath) => {
167
+ assert.equal(checkWorkflow(filePath), 2);
168
+ });
169
+ } finally {
170
+ console.error = originalError;
171
+ }
172
+ });
173
+
174
+ it('accepts a base_ref bound to any environment variable name', () => {
175
+ const workflow = `name: Test
176
+ on: pull_request
177
+ env:
178
+ GIT_CONFIG_KEY_0: init.defaultBranch
179
+ jobs:
180
+ test:
181
+ runs-on: ubuntu-latest
182
+ timeout-minutes: 5
183
+ concurrency:
184
+ group: \${{ github.workflow }}-\${{ github.ref }}-test
185
+ cancel-in-progress: true
186
+ steps:
187
+ - uses: actions/checkout@v6
188
+ - name: Simulate fresh merge
189
+ env:
190
+ BASE_REF: \${{ github.base_ref }}
191
+ run: bash scripts/simulate-fresh-merge.sh
192
+ `;
193
+
194
+ withWorkflow(workflow, (filePath) => {
195
+ assert.equal(checkWorkflow(filePath), 0);
196
+ });
197
+ });
198
+
199
+ it('still rejects a base_ref spliced into a run body', () => {
200
+ const workflow = `name: Test
201
+ on: pull_request
202
+ env:
203
+ GIT_CONFIG_KEY_0: init.defaultBranch
204
+ jobs:
205
+ test:
206
+ runs-on: ubuntu-latest
207
+ timeout-minutes: 5
208
+ concurrency:
209
+ group: \${{ github.workflow }}-\${{ github.ref }}-test
210
+ cancel-in-progress: true
211
+ steps:
212
+ - uses: actions/checkout@v6
213
+ - run: git fetch origin \${{ github.base_ref }}
214
+ `;
215
+ const originalError = console.error;
216
+ console.error = () => {};
217
+
218
+ try {
219
+ withWorkflow(workflow, (filePath) => {
220
+ assert.ok(checkWorkflow(filePath) > 0);
221
+ });
222
+ } finally {
223
+ console.error = originalError;
224
+ }
225
+ });
73
226
  });