Skip to content
This repository was archived by the owner on Jul 11, 2023. It is now read-only.

Commit c3bd1e0

Browse files
authored
Merge pull request #10 from jonabc/handle-exising-cards
Handle errors when adding cards
2 parents f21cab7 + 1cffa0c commit c3bd1e0

3 files changed

Lines changed: 128 additions & 20 deletions

File tree

dist/index.js

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,6 +1879,8 @@ module.exports = windowsRelease;
18791879
const projectCardContentFields = `
18801880
id
18811881
title
1882+
state
1883+
body
18821884
labels(first: 20) {
18831885
nodes {
18841886
name
@@ -5150,10 +5152,48 @@ function filterByLabel(cards) {
51505152
});
51515153
}
51525154

5155+
function filterByState(cards) {
5156+
let stateFilter = core.getInput('state_filter', { required: false });
5157+
if (!stateFilter) {
5158+
return cards;
5159+
}
5160+
5161+
stateFilter = stateFilter.toUpperCase();
5162+
return cards.filter(card => {
5163+
if (card.content) {
5164+
// only include cards for issues and PRs in a matching state
5165+
return card.content.state === stateFilter;
5166+
}
5167+
5168+
// don't filter cards that can't be filtered by state
5169+
return true;
5170+
});
5171+
}
5172+
5173+
const IGNORE_COMMENT = '<!-- mirror ignore -->';
5174+
function filterIgnored(cards) {
5175+
return cards.filter(card => {
5176+
if (card.note) {
5177+
// don't include cards that have the ignore comment in the note
5178+
return !card.note.includes(IGNORE_COMMENT);
5179+
}
5180+
5181+
if (card.content && card.content.body) {
5182+
// don't include cards that have the ignore comment in content body
5183+
return !card.content.body.includes(IGNORE_COMMENT);
5184+
}
5185+
5186+
// do not filter cards that can't include ignored stamps
5187+
return true;
5188+
});
5189+
}
5190+
51535191
module.exports = {
51545192
type: filterByType,
51555193
content: filterByContent,
5156-
label: filterByLabel
5194+
label: filterByLabel,
5195+
state: filterByState,
5196+
ignored: filterIgnored
51575197
};
51585198

51595199

@@ -5924,11 +5964,17 @@ async function addCard(api, card, column) {
59245964
cardData.note = card.note;
59255965
}
59265966

5927-
const response = await api(queries.ADD_PROJECT_CARD, {
5928-
columnId: column.id,
5929-
...cardData
5930-
});
5931-
return [response.addProjectCard.cardEdge.node, 0];
5967+
try {
5968+
const response = await api(queries.ADD_PROJECT_CARD, {
5969+
columnId: column.id,
5970+
...cardData
5971+
});
5972+
return [response.addProjectCard.cardEdge.node, 0];
5973+
} catch (error) {
5974+
core.warning(`Could not add card for payload ${JSON.stringify(cardData)}`);
5975+
core.warning(error.message);
5976+
return [null, -1];
5977+
}
59325978
}
59335979

59345980
// Call the GitHub API to move a card in a project column
@@ -5971,7 +6017,7 @@ async function run() {
59716017
// target column based on the remaining filters
59726018
const { sourceColumn, targetColumn } = response;
59736019
const sourceCards = applyFilters(sourceColumn.cards.nodes, [...Object.values(filters)]);
5974-
const targetCards = targetColumn.cards.nodes;
6020+
const targetCards = applyFilters(targetColumn.cards.nodes, [filters.ignored]);
59756021

59766022
// prepend the automation note card to the filtered source cards, so that
59776023
// it will be created if needed in the target column.
@@ -6003,7 +6049,10 @@ async function run() {
60036049
// this card needs to be found before further mutating the target cards
60046050
// array during this loop iteration
60056051
let afterCard = null;
6006-
if (sourceIndex > 0) {
6052+
6053+
if (sourceIndex > targetCards.length) {
6054+
afterCard = targetCards[targetCards.length - 1];
6055+
} else if (sourceIndex > 0) {
60076056
afterCard = targetCards[sourceIndex - 1];
60086057
}
60096058

@@ -6014,11 +6063,13 @@ async function run() {
60146063
[targetCard, targetIndex] = await addCard(api, sourceCard, targetColumn);
60156064

60166065
// add new card to local array and set index based on it's index in the column
6017-
targetCards.splice(targetIndex, 0, targetCard);
6066+
if (targetCard) {
6067+
targetCards.splice(targetIndex, 0, targetCard);
6068+
}
60186069
}
60196070

60206071
// move the card if it's not at the correct location
6021-
if (targetIndex !== sourceIndex) {
6072+
if (targetCard && targetIndex !== sourceIndex) {
60226073
// this for loop cannot be parallelized, as it is dependent on ordering
60236074
// eslint-disable-next-line no-await-in-loop
60246075
targetCard = await moveCard(api, targetCard, targetColumn, afterCard);

src/linked-project-columns.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,17 @@ async function addCard(api, card, column) {
4242
cardData.note = card.note;
4343
}
4444

45-
const response = await api(queries.ADD_PROJECT_CARD, {
46-
columnId: column.id,
47-
...cardData
48-
});
49-
return [response.addProjectCard.cardEdge.node, 0];
45+
try {
46+
const response = await api(queries.ADD_PROJECT_CARD, {
47+
columnId: column.id,
48+
...cardData
49+
});
50+
return [response.addProjectCard.cardEdge.node, 0];
51+
} catch (error) {
52+
core.warning(`Could not add card for payload ${JSON.stringify(cardData)}`);
53+
core.warning(error.message);
54+
return [null, -1];
55+
}
5056
}
5157

5258
// Call the GitHub API to move a card in a project column
@@ -121,7 +127,10 @@ async function run() {
121127
// this card needs to be found before further mutating the target cards
122128
// array during this loop iteration
123129
let afterCard = null;
124-
if (sourceIndex > 0) {
130+
131+
if (sourceIndex > targetCards.length) {
132+
afterCard = targetCards[targetCards.length - 1];
133+
} else if (sourceIndex > 0) {
125134
afterCard = targetCards[sourceIndex - 1];
126135
}
127136

@@ -132,11 +141,13 @@ async function run() {
132141
[targetCard, targetIndex] = await addCard(api, sourceCard, targetColumn);
133142

134143
// add new card to local array and set index based on it's index in the column
135-
targetCards.splice(targetIndex, 0, targetCard);
144+
if (targetCard) {
145+
targetCards.splice(targetIndex, 0, targetCard);
146+
}
136147
}
137148

138149
// move the card if it's not at the correct location
139-
if (targetIndex !== sourceIndex) {
150+
if (targetCard && targetIndex !== sourceIndex) {
140151
// this for loop cannot be parallelized, as it is dependent on ordering
141152
// eslint-disable-next-line no-await-in-loop
142153
targetCard = await moveCard(api, targetCard, targetColumn, afterCard);

test/linked-project-columns.test.js

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ describe('linked-project-columns', () => {
3838
};
3939

4040
sinon.spy(core, 'setFailed');
41+
sinon.spy(core, 'warning');
4142

4243
api = sinon.stub();
4344
sinon.stub(octokit.graphql, 'defaults').returns(api);
@@ -81,6 +82,7 @@ describe('linked-project-columns', () => {
8182

8283
await run();
8384

85+
expect(core.warning.callCount).toEqual(0);
8486
expect(core.setFailed.callCount).toEqual(1);
8587
expect(core.setFailed.getCall(0).args).toEqual(['Input required and not supplied: github_token']);
8688
});
@@ -90,6 +92,7 @@ describe('linked-project-columns', () => {
9092

9193
await run();
9294

95+
expect(core.warning.callCount).toEqual(0);
9396
expect(core.setFailed.callCount).toEqual(1);
9497
expect(core.setFailed.getCall(0).args).toEqual(['Input required and not supplied: source_column_id']);
9598
});
@@ -99,35 +102,39 @@ describe('linked-project-columns', () => {
99102

100103
await run();
101104

105+
expect(core.warning.callCount).toEqual(0);
102106
expect(core.setFailed.callCount).toEqual(1);
103107
expect(core.setFailed.getCall(0).args).toEqual(['Input required and not supplied: target_column_id']);
104108
});
105109

106110
it('queries for source and target column information', async () => {
107111
await run();
108112

113+
expect(core.warning.callCount).toEqual(0);
114+
expect(core.setFailed.callCount).toEqual(0);
109115
expect(api.callCount).toBeGreaterThanOrEqual(1);
110116
expect(api.getCall(0).args).toContain(queries.GET_PROJECT_COLUMNS);
111-
expect(core.setFailed.callCount).toEqual(0);
112117
});
113118

114119
it('adds an automation note to the target column', async () => {
115120
await run();
116121

122+
expect(core.warning.callCount).toEqual(0);
123+
expect(core.setFailed.callCount).toEqual(0);
117124
expect(api.callCount).toEqual(2);
118125
expect(api.getCall(1).args[0]).toEqual(queries.ADD_PROJECT_CARD);
119126
expect(api.getCall(1).args[1]).toMatchObject({
120127
columnId: 2,
121128
note: expect.stringMatching(/\*\*DO NOT EDIT\*\*/)
122129
});
123-
expect(core.setFailed.callCount).toEqual(0);
124130
});
125131

126132
it('deletes cards from the target column that are not in source', async () => {
127133
getColumnsResponse.targetColumn.cards.nodes.push({ id: 1, note: '1' }, { id: 2, note: '2' });
128134

129135
await run();
130136

137+
expect(core.warning.callCount).toEqual(0);
131138
expect(core.setFailed.callCount).toEqual(0);
132139
expect(api.callCount).toEqual(4);
133140
// deletions happen before adds
@@ -142,6 +149,7 @@ describe('linked-project-columns', () => {
142149

143150
await run();
144151

152+
expect(core.warning.callCount).toEqual(0);
145153
expect(core.setFailed.callCount).toEqual(0);
146154
expect(api.callCount).toEqual(6);
147155
// call 0 -> get columns
@@ -152,12 +160,38 @@ describe('linked-project-columns', () => {
152160
expect(api.getCall(5).args).toEqual([queries.MOVE_PROJECT_CARD, { columnId: 2, cardId: 202, afterCardId: 201 }]);
153161
});
154162

163+
it('logs a warning if a card cannot be added to the target', async () => {
164+
getColumnsResponse.sourceColumn.cards.nodes.push({ id: 1, note: '1' }, { id: 2, note: '2' });
165+
api
166+
.withArgs(queries.ADD_PROJECT_CARD)
167+
.onCall(1)
168+
.throws(new Error('test error'));
169+
170+
await run();
171+
172+
expect(core.warning.callCount).toEqual(2);
173+
expect(core.warning.getCall(0).args).toEqual(
174+
expect.arrayContaining([expect.stringContaining('Could not add card')])
175+
);
176+
expect(core.warning.getCall(1).args).toEqual(['test error']);
177+
expect(core.setFailed.callCount).toEqual(0);
178+
179+
expect(api.callCount).toEqual(5);
180+
// call 0 -> get columns
181+
// call 1 -> add automation note
182+
// the first card, with note '1' results in an error and won't have a secondary move call
183+
expect(api.getCall(2).args).toEqual([queries.ADD_PROJECT_CARD, { columnId: 2, note: '1' }]);
184+
expect(api.getCall(3).args).toEqual([queries.ADD_PROJECT_CARD, { columnId: 2, note: '2' }]);
185+
expect(api.getCall(4).args).toEqual([queries.MOVE_PROJECT_CARD, { columnId: 2, cardId: 201, afterCardId: 200 }]);
186+
});
187+
155188
it('moves cards on the target to match the source', async () => {
156189
getColumnsResponse.sourceColumn.cards.nodes.push({ id: 1, note: '1' }, { id: 2, note: '2' });
157190
getColumnsResponse.targetColumn.cards.nodes.push({ id: 202, note: '2' }, { id: 201, note: '1' });
158191

159192
await run();
160193

194+
expect(core.warning.callCount).toEqual(0);
161195
expect(core.setFailed.callCount).toEqual(0);
162196
expect(api.callCount).toEqual(3);
163197
// call 0 -> get columns
@@ -171,6 +205,7 @@ describe('linked-project-columns', () => {
171205

172206
await run();
173207

208+
expect(core.warning.callCount).toEqual(0);
174209
expect(core.setFailed.callCount).toEqual(0);
175210
expect(api.callCount).toEqual(4);
176211
// call 0 -> get columns
@@ -185,6 +220,7 @@ describe('linked-project-columns', () => {
185220

186221
await run();
187222

223+
expect(core.warning.callCount).toEqual(0);
188224
expect(core.setFailed.callCount).toEqual(0);
189225
expect(api.callCount).toEqual(4);
190226
// call 0 -> get columns
@@ -227,6 +263,7 @@ describe('linked-project-columns', () => {
227263

228264
await run();
229265

266+
expect(core.warning.callCount).toEqual(0);
230267
expect(core.setFailed.callCount).toEqual(0);
231268
expect(api.callCount).toEqual(4);
232269
// call 0 -> get columns
@@ -241,6 +278,7 @@ describe('linked-project-columns', () => {
241278

242279
await run();
243280

281+
expect(core.warning.callCount).toEqual(0);
244282
expect(core.setFailed.callCount).toEqual(0);
245283
expect(api.callCount).toEqual(4);
246284
// call 0 -> get columns
@@ -268,6 +306,7 @@ describe('linked-project-columns', () => {
268306

269307
await run();
270308

309+
expect(core.warning.callCount).toEqual(0);
271310
expect(core.setFailed.callCount).toEqual(0);
272311
expect(api.callCount).toEqual(6);
273312
// call 0 -> get columns
@@ -306,6 +345,7 @@ describe('linked-project-columns', () => {
306345

307346
await run();
308347

348+
expect(core.warning.callCount).toEqual(0);
309349
expect(core.setFailed.callCount).toEqual(0);
310350
expect(api.callCount).toEqual(6);
311351
// call 0 -> get columns
@@ -337,6 +377,7 @@ describe('linked-project-columns', () => {
337377

338378
await run();
339379

380+
expect(core.warning.callCount).toEqual(0);
340381
expect(core.setFailed.callCount).toEqual(0);
341382
expect(api.callCount).toEqual(4);
342383
// call 0 -> get columns
@@ -351,6 +392,7 @@ describe('linked-project-columns', () => {
351392

352393
await run();
353394

395+
expect(core.warning.callCount).toEqual(0);
354396
expect(core.setFailed.callCount).toEqual(0);
355397
expect(api.callCount).toEqual(4);
356398
// call 0 -> get columns
@@ -367,6 +409,7 @@ describe('linked-project-columns', () => {
367409

368410
await run();
369411

412+
expect(core.warning.callCount).toEqual(0);
370413
expect(core.setFailed.callCount).toEqual(0);
371414
expect(api.callCount).toEqual(2);
372415
// call 0 -> get columns
@@ -379,6 +422,7 @@ describe('linked-project-columns', () => {
379422

380423
await run();
381424

425+
expect(core.warning.callCount).toEqual(0);
382426
expect(core.setFailed.callCount).toEqual(0);
383427
expect(api.callCount).toEqual(2);
384428
// call 0 -> get columns
@@ -394,6 +438,7 @@ describe('linked-project-columns', () => {
394438

395439
await run();
396440

441+
expect(core.warning.callCount).toEqual(0);
397442
expect(core.setFailed.callCount).toEqual(0);
398443
expect(api.callCount).toEqual(2);
399444
// call 0 -> get columns
@@ -406,6 +451,7 @@ describe('linked-project-columns', () => {
406451

407452
await run();
408453

454+
expect(core.warning.callCount).toEqual(0);
409455
expect(core.setFailed.callCount).toEqual(0);
410456
expect(api.callCount).toEqual(2);
411457
// call 0 -> get columns

0 commit comments

Comments
 (0)