Skip to content

Commit 4ac8b4e

Browse files
authored
feat: allow to use * at the beginning and the middle of repository name patterns (#37)
1 parent d252719 commit 4ac8b4e

File tree

3 files changed

+145
-64
lines changed

3 files changed

+145
-64
lines changed

lib/resolve-repositories.js

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
export async function resolveRepositories(state, repositories) {
2-
const invalidRepositories = repositories.filter((fullName) => {
3-
/^[a-z0-9_.-]+\/([a-z0-9_.-]+|\*)$/i.test(fullName);
4-
});
5-
6-
if (invalidRepositories.length) {
7-
throw new Error("[octoherd] Invalid repositories: %o", invalidRepositories);
8-
}
9-
102
const repositoriesWithStars = repositories.filter((fullName) => {
11-
return /^[a-z0-9_.-]+\/[a-z0-9_.-]*\*$/i.test(fullName);
3+
return /^[a-z0-9_.-]+\/(\*|[a-z0-9_.-]+\*|\*[a-z0-9_.-]+|[a-z0-9_.-]+\*[a-z0-9_.-]+)$/i.test(
4+
fullName
5+
);
126
});
137

148
const repositoriesWithoutStars = repositories.filter((fullName) => {
@@ -59,9 +53,11 @@ export async function resolveRepositories(state, repositories) {
5953
)) {
6054
let selectedRepositories = response.data;
6155

62-
if (repoPattern !== '*') {
63-
const repoRegex = new RegExp(`^${repoPattern.replace(/\*/g, '.*')}$`)
64-
selectedRepositories = selectedRepositories.filter(repo => repoRegex.test(repo.name))
56+
if (repoPattern !== "*") {
57+
const repoRegex = new RegExp(`^${repoPattern.replace(/\*/g, ".*")}$`);
58+
selectedRepositories = selectedRepositories.filter((repo) =>
59+
repoRegex.test(repo.name)
60+
);
6561
}
6662

6763
resolvedRepositories.push(...selectedRepositories);

lib/run-script-against-repositories.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@ export async function runScriptAgainstRepositories(state, octoherdRepos = []) {
1414
validate(input) {
1515
const values = typeof input === "string" ? [input] : input;
1616

17-
const invalid = values.find(
18-
(value) =>
19-
!/^([a-z0-9_.-]+\/([a-z0-9_.-]+|\*)|\*)$/.test(value.trim())
20-
);
17+
const invalid = values.find((value) => {
18+
if (value.trim() === "*") return;
19+
20+
if (/^[a-z0-9_.-]+\/[a-z0-9_.*-]+$/.test(value.trim())) {
21+
return;
22+
}
23+
24+
return true;
25+
});
2126

2227
if (!invalid) return true;
2328

tests/resolve-repositories.test.js

Lines changed: 128 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -75,54 +75,134 @@ withOrg("when requesting all the repositories", async () => {
7575
equal(resolvedRepos, mockedResponse);
7676
});
7777

78-
withOrg("when requesting all the repositories under a pattern", async () => {
79-
const org = "octoherd";
80-
const repo = "script-*";
81-
const octokit = new Octokit({
82-
auth: process.env.GITHUB_TOKEN,
83-
});
84-
85-
const repositories = [`${org}/${repo}`];
86-
87-
const scriptRepos = [
88-
{ name: "script-close-renovate-dashboard-issues" },
89-
{ name: "script-create-repositories-from-script-folders" },
90-
{ name: "script-find-releases" },
91-
{ name: "script-remove-dependabot" },
92-
{ name: "script-remove-required-ci-check" },
93-
{ name: "script-setup-renovate" },
94-
{ name: "script-star-or-unstar" },
95-
{ name: "script-sync-branch-protections" },
96-
{ name: "script-add-octoherd-cli-to-script" },
97-
{ name: "script-hello-world" },
98-
];
99-
100-
const nonScriptRepos = [
101-
{ name: "cli" },
102-
{ name: "octoherd" },
103-
{ name: ".github" },
104-
{ name: "octokit" },
105-
{ name: "create-octoherd-script }" },
106-
];
107-
108-
simple.mock(octokit, "request").resolveWith(undefined);
109-
110-
simple.mock(octokit.paginate, "iterator").returnWith({
111-
async *[Symbol.asyncIterator]() {
112-
yield { data: [...scriptRepos, ...nonScriptRepos] };
113-
},
114-
});
115-
116-
const resolvedRepos = await resolveRepositories(
117-
{
118-
log: console,
119-
octokit,
120-
},
121-
repositories
122-
);
123-
124-
equal(resolvedRepos, scriptRepos);
125-
});
78+
withOrg(
79+
"when requesting all the repositories with pattern at end",
80+
async () => {
81+
const org = "octoherd";
82+
const repo = "script-*";
83+
const octokit = new Octokit({
84+
auth: process.env.GITHUB_TOKEN,
85+
});
86+
87+
const repositories = [`${org}/${repo}`];
88+
89+
const scriptRepos = [
90+
{ name: "script-close-renovate-dashboard-issues" },
91+
{ name: "script-create-repositories-from-script-folders" },
92+
{ name: "script-find-releases" },
93+
{ name: "script-remove-dependabot" },
94+
{ name: "script-remove-required-ci-check" },
95+
{ name: "script-setup-renovate" },
96+
{ name: "script-star-or-unstar" },
97+
{ name: "script-sync-branch-protections" },
98+
{ name: "script-add-octoherd-cli-to-script" },
99+
{ name: "script-hello-world" },
100+
];
101+
102+
const nonScriptRepos = [
103+
{ name: "cli" },
104+
{ name: "octoherd" },
105+
{ name: ".github" },
106+
{ name: "octokit" },
107+
{ name: "create-octoherd-script }" },
108+
];
109+
110+
simple.mock(octokit, "request").resolveWith(undefined);
111+
112+
simple.mock(octokit.paginate, "iterator").returnWith({
113+
async *[Symbol.asyncIterator]() {
114+
yield { data: [...scriptRepos, ...nonScriptRepos] };
115+
},
116+
});
117+
118+
const resolvedRepos = await resolveRepositories(
119+
{
120+
log: console,
121+
octokit,
122+
},
123+
repositories
124+
);
125+
126+
equal(resolvedRepos, scriptRepos);
127+
}
128+
);
129+
130+
withOrg(
131+
"when requesting all the repositories with pattern at end",
132+
async () => {
133+
const org = "octoherd";
134+
const repo = "*-test";
135+
const octokit = new Octokit({
136+
auth: process.env.GITHUB_TOKEN,
137+
});
138+
139+
const repositories = [`${org}/${repo}`];
140+
141+
const testRepos = [
142+
{ name: "one-test" },
143+
{ name: "two-test" },
144+
{ name: "three-test" },
145+
];
146+
147+
const nonTestRepos = [{ name: "foo" }, { name: "bar" }];
148+
149+
simple.mock(octokit, "request").resolveWith(undefined);
150+
151+
simple.mock(octokit.paginate, "iterator").returnWith({
152+
async *[Symbol.asyncIterator]() {
153+
yield { data: [...testRepos, ...nonTestRepos] };
154+
},
155+
});
156+
157+
const resolvedRepos = await resolveRepositories(
158+
{
159+
log: console,
160+
octokit,
161+
},
162+
repositories
163+
);
164+
165+
equal(resolvedRepos, testRepos);
166+
}
167+
);
168+
withOrg(
169+
"when requesting all the repositories with pattern in the middle",
170+
async () => {
171+
const org = "octoherd";
172+
const repo = "middle-*-test";
173+
const octokit = new Octokit({
174+
auth: process.env.GITHUB_TOKEN,
175+
});
176+
177+
const repositories = [`${org}/${repo}`];
178+
179+
const testRepos = [
180+
{ name: "middle-one-test" },
181+
{ name: "middle-two-test" },
182+
{ name: "middle-three-test" },
183+
];
184+
185+
const nonTestRepos = [{ name: "foo" }, { name: "bar" }];
186+
187+
simple.mock(octokit, "request").resolveWith(undefined);
188+
189+
simple.mock(octokit.paginate, "iterator").returnWith({
190+
async *[Symbol.asyncIterator]() {
191+
yield { data: [...testRepos, ...nonTestRepos] };
192+
},
193+
});
194+
195+
const resolvedRepos = await resolveRepositories(
196+
{
197+
log: console,
198+
octokit,
199+
},
200+
repositories
201+
);
202+
203+
equal(resolvedRepos, testRepos);
204+
}
205+
);
126206

127207
withUser("when single repository exists", async () => {
128208
const owner = "gr2m";

0 commit comments

Comments
 (0)