Skip to content

Commit c1cae08

Browse files
authored
Merge pull request #5 from gitops-toolbox/feature/fail_if_one_template_is_invalid
Fail if even one template is invalid
2 parents a97fa73 + 9b61f9c commit c1cae08

6 files changed

Lines changed: 256 additions & 198 deletions

File tree

lib/github.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,19 @@ class Github {
3939
return invalid;
4040
}
4141

42-
prepare_actions() {
42+
_prepare_actions() {
4343
const templates = this.templates;
44-
const actions = {
45-
invalid: [],
46-
by_repo: {},
47-
};
44+
const actions = {};
4845

4946
for (const template of templates) {
5047
const params = template.destination.params;
51-
if (!this.isValid(template)) {
52-
actions.invalid.push(template);
53-
continue;
54-
}
5548

56-
if (!actions.by_repo[params.repo]) {
57-
actions.by_repo[params.repo] = [];
49+
if (!actions[params.repo]) {
50+
actions[params.repo] = [];
5851
}
5952
this.logger('Template %o', template);
60-
this.logger('Added to: %o', actions.by_repo[params.repo]);
61-
actions.by_repo[params.repo].push(template);
53+
this.logger('Added to: %o', actions[params.repo]);
54+
actions[params.repo].push(template);
6255
}
6356

6457
return actions;
@@ -96,9 +89,9 @@ class Github {
9689
return results;
9790
}
9891

99-
preparePRs(actions) {
92+
_preparePRs(actions) {
10093
const pr_by_repo = {};
101-
for (const [repo, templates] of Object.entries(actions.by_repo)) {
94+
for (const [repo, templates] of Object.entries(actions)) {
10295
let body = [];
10396
const generating = [];
10497
const deleting = [];
@@ -154,7 +147,7 @@ class Github {
154147
}
155148

156149
async _apply(actions) {
157-
const pr_by_repo = this.preparePRs(actions);
150+
const pr_by_repo = this._preparePRs(actions);
158151
const results = {};
159152
for (const [repo, prData] of Object.entries(pr_by_repo)) {
160153
try {
@@ -167,6 +160,7 @@ class Github {
167160
prData.base || false,
168161
prData.draft || false
169162
);
163+
170164
results[repo] = (await pr.get()).html_url;
171165
} catch (e) {
172166
results[repo] = e.message;
@@ -176,7 +170,13 @@ class Github {
176170
}
177171

178172
async persist() {
179-
const actions = this.prepare_actions();
173+
const invalid = this.filterInvalid();
174+
if (invalid.length > 0) {
175+
return {
176+
invalidTemplates: invalid,
177+
};
178+
}
179+
const actions = this._prepare_actions();
180180
return await this._apply(actions);
181181
}
182182
}

test/create_pr.test.js

Lines changed: 150 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,113 @@ const args = {
1414
interactive: false,
1515
};
1616

17+
function openPR(message, branch, title, body, changes) {
18+
return {
19+
get: () => {
20+
return new Promise((resolve) => {
21+
resolve({
22+
html_url: {
23+
message,
24+
branch,
25+
changes,
26+
body,
27+
},
28+
});
29+
});
30+
},
31+
};
32+
}
33+
34+
tap.test('When opening a PR', (t) => {
35+
t.plan(2);
36+
37+
t.afterEach((t) => {
38+
sinon.restore();
39+
});
40+
41+
t.test('Error should be returned if cannot open a PR', async (t) => {
42+
sinon.replace(
43+
TpdGithub.prototype,
44+
'_tryGetRepoInfo',
45+
sinon.fake.throws('Failing to simulate error in tests')
46+
);
47+
sinon.replace(
48+
Repo.prototype,
49+
'openPR',
50+
sinon.fake.throws('Failed to open PR')
51+
);
52+
53+
const tpdGithub = new TpdGithub(
54+
require('./fixtures/valid.json'),
55+
logger,
56+
args
57+
);
58+
59+
const prs = await tpdGithub.persist();
60+
61+
t.strictSame(prs, {
62+
'LucaLanziani/giggi': 'Failed to open PR',
63+
});
64+
});
65+
66+
t.test(
67+
'If remote origin available should open pr with the repo reference',
68+
async (t) => {
69+
t.plan(4);
70+
const repoInfos = [
71+
'git@github.com:gitops-toolbox/templator.git',
72+
'7654321',
73+
'https://github.com/gitops-toolbox/templator.git',
74+
'1234567',
75+
'http://github.com/gitops-toolbox/templator.git',
76+
'7890123',
77+
'url/format/not/supported',
78+
'123345345',
79+
];
80+
81+
const expected = 'Generated from gitops-toolbox/templator@';
82+
83+
sinon.replace(Repo.prototype, 'openPR', openPR);
84+
85+
sinon.stub(child_process, 'execSync').callsFake(() => {
86+
return repoInfos.shift();
87+
});
88+
89+
const tpdGithub = new TpdGithub(
90+
require('./fixtures/valid.json'),
91+
logger,
92+
args
93+
);
94+
95+
const git = await tpdGithub.persist();
96+
const https = await tpdGithub.persist();
97+
const http = await tpdGithub.persist();
98+
99+
const notSupported = await tpdGithub.persist();
100+
101+
t.same(http['LucaLanziani/giggi'].message, `${expected}7890123`);
102+
t.same(https['LucaLanziani/giggi'].message, `${expected}1234567`);
103+
t.same(git['LucaLanziani/giggi'].message, `${expected}7654321`);
104+
t.same(
105+
notSupported['LucaLanziani/giggi'].message,
106+
`Generated with templator`
107+
);
108+
}
109+
);
110+
});
111+
17112
tap.test('When instatiating a new TpdGithub object', (t) => {
18-
t.plan(7);
113+
t.plan(5);
19114

20115
t.beforeEach((t) => {
21-
t.context.repoStub = sinon.stub(Repo.prototype, 'openPR');
22116
sinon.replace(
23117
TpdGithub.prototype,
24118
'_tryGetRepoInfo',
25119
sinon.fake.throws('Failing to simulate error in tests')
26120
);
121+
122+
sinon.replace(Repo.prototype, 'openPR', openPR);
123+
27124
t.context.original_log = console.log;
28125
console.log = debug;
29126
fs.mkdirSync(destination_path);
@@ -55,49 +152,85 @@ tap.test('When instatiating a new TpdGithub object', (t) => {
55152
}
56153
);
57154

58-
t.test('Will split actions per repos', async (t) => {
155+
t.test('Will open a PR per repo', async (t) => {
59156
t.plan(1);
60-
61-
const actions = new TpdGithub(
62-
require('./fixtures/templates.json'),
157+
const fixture = require('./fixtures/templates.js');
158+
const PRs = await new TpdGithub(
159+
Object.values(fixture),
63160
logger,
64161
args
65-
).prepare_actions();
162+
).persist();
66163

67-
t.strictSame(actions, require('./fixtures/actions.js'));
164+
t.strictSame(PRs, {
165+
invalidTemplates: [
166+
fixture['missing/template/deep/folder/multiple/levels/text.txt'],
167+
],
168+
});
68169
});
69170

70171
t.test('Will generate multiple Prs', async (t) => {
71172
t.plan(1);
173+
const fixture = require('./fixtures/actions.js');
72174
const tpdGithub = new TpdGithub(
73-
require('./fixtures/templates.json'),
175+
Object.values(fixture).flat(),
74176
logger,
75177
args
76178
);
77179

78-
const actions = tpdGithub.prepare_actions();
79-
const prs_by_repo = tpdGithub.preparePRs(actions);
180+
const PRs = await tpdGithub.persist();
181+
182+
t.strictSame(PRs, {
183+
'org1/repo1': {
184+
message: 'Generated with templator',
185+
branch:
186+
'ci_1c4652b83af0c32c9ba0377dbaaa96c026bf3d80f03ce68e1d6abfce52972002',
187+
body: 'Generate:\nfile1.txt\nexistingDir/text.txt\n',
188+
changes: {
189+
'file1.txt': {
190+
mode: 'normal',
191+
content: 'test',
192+
},
193+
'existingDir/text.txt': {
194+
mode: 'normal',
195+
content: 'test',
196+
},
197+
},
198+
},
199+
'org2/repo1': {
200+
message: 'Generated with templator',
201+
branch:
202+
'ci_ef1071136cffc393333da2c62665a779cbeeb7b7516220a908174012537424d2',
203+
changes: {
204+
'deep/folder/multiple/levels/text.txt': {
205+
mode: 'normal',
206+
content: 'test',
207+
},
208+
'deep/folder/multiple/levels/old.txt': null,
209+
},
210+
body: `Generate:
211+
deep/folder/multiple/levels/text.txt
80212
81-
t.strictSame(prs_by_repo, require('./fixtures/prs_by_repo.js'));
213+
Delete:
214+
deep/folder/multiple/levels/old.txt`,
215+
},
216+
});
82217
});
83218

84-
t.test('Will a PR to delete files', async (t) => {
219+
t.test('Will open a PR to delete files', async (t) => {
85220
t.plan(1);
86221
const tpdGithub = new TpdGithub(
87222
require('./fixtures/valid.json'),
88223
logger,
89224
args
90225
);
91226

92-
const actions = tpdGithub.prepare_actions();
93-
const prs_by_repo = tpdGithub.preparePRs(actions);
227+
const prs = await tpdGithub.persist();
94228

95-
t.strictSame(prs_by_repo, {
229+
t.strictSame(prs, {
96230
'LucaLanziani/giggi': {
97231
message: 'Generated with templator',
98232
branch:
99233
'ci_328a4a8e3fc13ab478b0836e7086122d497dee2fdc33f14d0d80ba0e7a0d6936',
100-
title: 'Generated with templator',
101234
body: 'Delete:\ntest.txt\nfolder/application.json',
102235
changes: {
103236
'test.txt': null,
@@ -106,66 +239,4 @@ tap.test('When instatiating a new TpdGithub object', (t) => {
106239
},
107240
});
108241
});
109-
110-
t.test('Will try to open two prs', async (t) => {
111-
t.plan(1);
112-
const tpdGithub = new TpdGithub(
113-
require('./fixtures/templates.json'),
114-
logger,
115-
args
116-
);
117-
118-
await tpdGithub.persist();
119-
t.ok(t.context.repoStub.withArgs({}).onFirstCall());
120-
});
121-
122-
t.test(
123-
'If remote origin available should open pr with the repo reference',
124-
(t) => {
125-
t.plan(8);
126-
const repoInfos = [
127-
'git@github.com:gitops-toolbox/templator.git',
128-
'7654321',
129-
'https://github.com/gitops-toolbox/templator.git',
130-
'1234567',
131-
'http://github.com/gitops-toolbox/templator.git',
132-
'7890123',
133-
'url/format/not/supported',
134-
'123345345',
135-
];
136-
const expected = 'Generated from gitops-toolbox/templator@';
137-
sinon.restore();
138-
sinon.stub(child_process, 'execSync').callsFake(() => {
139-
return repoInfos.shift();
140-
});
141-
const tpdGithub = new TpdGithub(
142-
require('./fixtures/valid.json'),
143-
logger,
144-
args
145-
);
146-
147-
const git = tpdGithub.preparePRs(tpdGithub.prepare_actions())[
148-
'LucaLanziani/giggi'
149-
];
150-
const https = tpdGithub.preparePRs(tpdGithub.prepare_actions())[
151-
'LucaLanziani/giggi'
152-
];
153-
const http = tpdGithub.preparePRs(tpdGithub.prepare_actions())[
154-
'LucaLanziani/giggi'
155-
];
156-
157-
const notSupported = tpdGithub.preparePRs(tpdGithub.prepare_actions())[
158-
'LucaLanziani/giggi'
159-
];
160-
161-
t.same(http.message, `${expected}7890123`);
162-
t.same(http.title, `${expected}7890123`);
163-
t.same(https.message, `${expected}1234567`);
164-
t.same(https.title, `${expected}1234567`);
165-
t.same(git.message, `${expected}7654321`);
166-
t.same(git.title, `${expected}7654321`);
167-
t.same(notSupported.message, `Generated with templator`);
168-
t.same(notSupported.title, `Generated with templator`);
169-
}
170-
);
171242
});

0 commit comments

Comments
 (0)