Skip to content

Commit 20d1f8e

Browse files
committed
use zod union
1 parent f2a4688 commit 20d1f8e

File tree

2 files changed

+165
-144
lines changed

2 files changed

+165
-144
lines changed

lib/modules/manager/github-actions/extract.spec.ts

+77-58
Original file line numberDiff line numberDiff line change
@@ -707,74 +707,56 @@ describe('modules/manager/github-actions/extract', () => {
707707
]);
708708
});
709709

710-
it('extracts package from community actions', () => {
711-
const yamlContent = dump({
712-
jobs: {
713-
build: {
714-
steps: [
715-
{
716-
name: 'Pinning a minor version of uv',
717-
uses: 'astral-sh/setup-uv@v5',
718-
with: {
719-
version: 'latest',
720-
},
721-
},
722-
{
723-
uses: 'pnpm/action-setup@v4',
724-
with: {
725-
version: 'latest',
726-
},
727-
},
728-
{
729-
name: 'Install gotestsum',
730-
uses: 'jaxxstorm/[email protected]',
731-
with: {
732-
repo: 'gotestyourself/gotestsum',
733-
tag: 'v1.12.1',
734-
platform: 'linux',
735-
arch: 'amd64',
736-
},
737-
},
738-
{
739-
name: 'Pinning a minor version of uv',
740-
uses: 'astral-sh/setup-uv@v5',
741-
with: {
742-
version: '0.4.x',
743-
},
744-
},
745-
{
746-
uses: 'pnpm/action-setup@v4',
747-
with: {
748-
version: 10,
749-
},
750-
},
751-
{
752-
uses: 'pnpm/action-setup@v4',
753-
with: {
754-
version: '10.x',
755-
},
756-
},
757-
{
758-
uses: 'pdm-project/[email protected]',
759-
with: {
760-
version: '1.2.3',
761-
},
762-
},
763-
],
710+
it.each([
711+
{
712+
step: {
713+
uses: 'astral-sh/setup-uv@v5',
714+
with: {
715+
version: 'latest',
764716
},
765717
},
766-
});
718+
expected: [],
719+
},
767720

768-
const res = extractPackageFile(yamlContent, 'workflow.yml');
769-
expect(res?.deps.filter((pkg) => pkg.depType !== 'action')).toMatchObject(
770-
[
721+
{
722+
step: {
723+
uses: 'pnpm/action-setup@v4',
724+
with: {
725+
version: 'latest',
726+
},
727+
},
728+
expected: [],
729+
},
730+
{
731+
step: {
732+
name: 'Install gotestsum',
733+
uses: 'jaxxstorm/[email protected]',
734+
with: {
735+
repo: 'gotestyourself/gotestsum',
736+
tag: 'v1.12.1',
737+
platform: 'linux',
738+
arch: 'amd64',
739+
},
740+
},
741+
expected: [
771742
{
772743
currentValue: 'v1.12.1',
773744
datasource: 'github-releases',
774745
depName: 'gotestyourself/gotestsum',
775746
depType: 'uses-with',
776747
packageName: 'gotestyourself/gotestsum',
777748
},
749+
],
750+
},
751+
{
752+
step: {
753+
name: 'Pinning a minor version of uv',
754+
uses: 'astral-sh/setup-uv@v5',
755+
with: {
756+
version: '0.4.x',
757+
},
758+
},
759+
expected: [
778760
{
779761
currentValue: '0.4.x',
780762
datasource: 'github-releases',
@@ -783,6 +765,16 @@ describe('modules/manager/github-actions/extract', () => {
783765
packageName: 'astral-sh/uv',
784766
versioning: 'npm',
785767
},
768+
],
769+
},
770+
{
771+
step: {
772+
uses: 'pnpm/action-setup@v4',
773+
with: {
774+
version: 10,
775+
},
776+
},
777+
expected: [
786778
{
787779
currentValue: '10',
788780
datasource: 'npm',
@@ -791,6 +783,16 @@ describe('modules/manager/github-actions/extract', () => {
791783
packageName: 'pnpm',
792784
versioning: 'npm',
793785
},
786+
],
787+
},
788+
{
789+
step: {
790+
uses: 'pnpm/action-setup@v4',
791+
with: {
792+
version: '10.x',
793+
},
794+
},
795+
expected: [
794796
{
795797
currentValue: '10.x',
796798
datasource: 'npm',
@@ -799,6 +801,16 @@ describe('modules/manager/github-actions/extract', () => {
799801
packageName: 'pnpm',
800802
versioning: 'npm',
801803
},
804+
],
805+
},
806+
{
807+
step: {
808+
uses: 'pdm-project/[email protected]',
809+
with: {
810+
version: '1.2.3',
811+
},
812+
},
813+
expected: [
802814
{
803815
currentValue: '1.2.3',
804816
datasource: 'pypi',
@@ -808,6 +820,13 @@ describe('modules/manager/github-actions/extract', () => {
808820
versioning: 'pep440',
809821
},
810822
],
823+
},
824+
])('', async ({ step, expected }) => {
825+
const yamlContent = dump({ jobs: { build: { steps: [step] } } });
826+
827+
const res = extractPackageFile(yamlContent, 'workflow.yml');
828+
expect(res?.deps.filter((pkg) => pkg.depType !== 'action')).toMatchObject(
829+
expected,
811830
);
812831
});
813832
});

lib/modules/manager/github-actions/extract.ts

+88-86
Original file line numberDiff line numberDiff line change
@@ -198,88 +198,94 @@ function extractRunners(runner: unknown): PackageDependency[] {
198198
return runners.map(extractRunner).filter(isNotNullOrUndefined);
199199
}
200200

201-
const communityActions = [
202-
{
203-
// https://github.com/jaxxstorm/action-install-gh-release
204-
use: /^jaxxstorm\/action-install-gh-release@.*$/,
205-
schema: z
206-
.object({ with: z.object({ repo: z.string(), tag: z.string() }) })
207-
.transform(({ with: val }): PackageDependency => {
208-
return {
209-
datasource: GithubReleasesDatasource.id,
210-
depName: val.repo,
211-
packageName: val.repo,
212-
currentValue: val.tag,
213-
depType: 'uses-with',
214-
};
215-
}),
216-
},
217-
{
218-
// https://github.com/astral-sh/setup-uv
219-
use: /^astral-sh\/setup-uv@.*$/,
220-
schema: z
221-
.object({ with: z.object({ version: z.string() }) })
222-
.transform(({ with: val }): PackageDependency | undefined => {
223-
if (val.version === 'latest') {
224-
return;
225-
}
201+
const communityActions = z.union([
202+
z
203+
.object({
204+
// https://github.com/jaxxstorm/action-install-gh-release
205+
uses: z
206+
.string()
207+
.regex(
208+
/^(https:\/\/github\.com\/)?jaxxstorm\/action-install-gh-release@.*$/,
209+
),
210+
with: z.object({ repo: z.string(), tag: z.string() }),
211+
})
212+
.transform(({ with: val }): PackageDependency => {
213+
return {
214+
datasource: GithubReleasesDatasource.id,
215+
depName: val.repo,
216+
packageName: val.repo,
217+
currentValue: val.tag,
218+
depType: 'uses-with',
219+
};
220+
}),
221+
z
222+
.object({
223+
// https://github.com/astral-sh/setup-uv
224+
uses: z
225+
.string()
226+
.regex(/^(https:\/\/github\.com\/)?astral-sh\/setup-uv@.*$/),
227+
with: z.object({ version: z.string() }),
228+
})
229+
.transform(({ with: val }): PackageDependency | undefined => {
230+
if (val.version === 'latest') {
231+
return;
232+
}
226233

227-
return {
228-
datasource: GithubReleasesDatasource.id,
229-
depName: 'astral-sh/uv',
230-
versioning: npmVersioning.id,
231-
packageName: 'astral-sh/uv',
232-
currentValue: val.version,
233-
depType: 'uses-with',
234-
};
234+
return {
235+
datasource: GithubReleasesDatasource.id,
236+
depName: 'astral-sh/uv',
237+
versioning: npmVersioning.id,
238+
packageName: 'astral-sh/uv',
239+
currentValue: val.version,
240+
depType: 'uses-with',
241+
};
242+
}),
243+
z
244+
.object({
245+
// https://github.com/pnpm/action-setup
246+
uses: z
247+
.string()
248+
.regex(/^(https:\/\/github\.com\/)?pnpm\/action-setup@.*$/),
249+
with: z.object({
250+
version: z.union([
251+
z.string(),
252+
z.number().transform((s) => s.toString()),
253+
]),
235254
}),
236-
},
237-
{
238-
// https://github.com/pnpm/action-setup
239-
use: /^pnpm\/action-setup@.*$/,
240-
schema: z
241-
.object({
242-
with: z.object({
243-
version: z.union([
244-
z.string(),
245-
z.number().transform((s) => s.toString()),
246-
]),
247-
}),
248-
})
249-
.transform(({ with: val }): PackageDependency | undefined => {
250-
if (val.version === 'latest') {
251-
return;
252-
}
255+
})
256+
.transform(({ with: val }): PackageDependency | undefined => {
257+
if (val.version === 'latest') {
258+
return;
259+
}
253260

254-
return {
255-
datasource: NpmDatasource.id,
256-
depName: 'pnpm',
257-
versioning: npmVersioning.id,
258-
packageName: 'pnpm',
259-
currentValue: val.version,
260-
depType: 'uses-with',
261-
};
262-
}),
263-
},
264-
{
265-
// https://github.com/astral-sh/setup-uv
266-
use: /^pdm-project\/setup-pdm@.*$/,
267-
schema: z
268-
.object({
269-
with: z.object({ version: z.string().refine((s) => s !== 'head') }),
270-
})
271-
.transform(({ with: val }): PackageDependency | undefined => {
272-
return {
273-
datasource: PypiDatasource.id,
274-
depName: 'pdm',
275-
versioning: pep440versioning.id,
276-
packageName: 'pdm',
277-
currentValue: val.version,
278-
depType: 'uses-with',
279-
};
280-
}),
281-
},
282-
];
261+
return {
262+
datasource: NpmDatasource.id,
263+
depName: 'pnpm',
264+
versioning: npmVersioning.id,
265+
packageName: 'pnpm',
266+
currentValue: val.version,
267+
depType: 'uses-with',
268+
};
269+
}),
270+
z
271+
.object({
272+
// https://github.com/astral-sh/setup-uv
273+
uses: z
274+
.string()
275+
.regex(/^(https:\/\/github\.com\/)?pdm-project\/setup-pdm@.*$/),
276+
with: z.object({ version: z.string().refine((s) => s !== 'head') }),
277+
})
278+
.transform(({ with: val }): PackageDependency | undefined => {
279+
return {
280+
datasource: PypiDatasource.id,
281+
depName: 'pdm',
282+
versioning: pep440versioning.id,
283+
packageName: 'pdm',
284+
currentValue: val.version,
285+
depType: 'uses-with',
286+
};
287+
}),
288+
]);
283289

284290
function extractWithYAMLParser(
285291
content: string,
@@ -335,13 +341,9 @@ function extractWithYAMLParser(
335341

336342
for (const step of coerceArray(job?.steps)) {
337343
if (step.uses) {
338-
for (const action of communityActions) {
339-
if (action.use.test(step.uses)) {
340-
const val = Result.parse(step, action.schema).unwrapOrNull();
341-
if (val) {
342-
deps.push(val);
343-
}
344-
}
344+
const val = Result.parse(step, communityActions).unwrapOrNull();
345+
if (val) {
346+
deps.push(val);
345347
}
346348
}
347349

0 commit comments

Comments
 (0)