Skip to content

Commit 8bc0bd4

Browse files
authored
feat: add fail-if-item-not-found input to more actions (#42)
1 parent 64f724e commit 8bc0bd4

16 files changed

+110
-15
lines changed

.github/workflows/integration-tests.yml

+33
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,18 @@ jobs:
172172
project-number: ${{ steps.copy-project.outputs.number }}
173173
token: ${{ steps.get-auth-token.outputs.token }}
174174

175+
- name: Edit Item (Not Found)
176+
uses: ./edit-item/
177+
id: edit-item-not-found
178+
with:
179+
fail-if-item-not-found: false
180+
field: Priority
181+
field-value: ⛰️ High
182+
item: foobar
183+
owner: ${{ steps.copy-project.outputs.owner }}
184+
project-number: ${{ steps.copy-project.outputs.number }}
185+
token: ${{ steps.get-auth-token.outputs.token }}
186+
175187
- name: Get Item
176188
uses: ./get-item/
177189
id: get-edited-item
@@ -182,6 +194,17 @@ jobs:
182194
project-number: ${{ steps.copy-project.outputs.number }}
183195
token: ${{ steps.get-auth-token.outputs.token }}
184196

197+
- name: Get Item (Not Found)
198+
uses: ./get-item/
199+
id: get-item-not-found
200+
with:
201+
fail-if-item-not-found: false
202+
field: Priority
203+
item: foobar
204+
owner: ${{ steps.copy-project.outputs.owner }}
205+
project-number: ${{ steps.copy-project.outputs.number }}
206+
token: ${{ steps.get-auth-token.outputs.token }}
207+
185208
- name: Check Edited Item Field Value
186209
uses: ./github-script/
187210
with:
@@ -236,6 +259,16 @@ jobs:
236259
project-number: ${{ steps.copy-project.outputs.number }}
237260
token: ${{ steps.get-auth-token.outputs.token }}
238261

262+
- name: Delete Item (Not Found)
263+
uses: ./delete-item/
264+
id: delete-item-not-found
265+
with:
266+
item: foobar
267+
fail-if-item-not-found: false
268+
owner: ${{ steps.copy-project.outputs.owner }}
269+
project-number: ${{ steps.copy-project.outputs.number }}
270+
token: ${{ steps.get-auth-token.outputs.token }}
271+
239272
- name: Link Project to Repository
240273
uses: ./link-project/
241274
id: link-project-to-repo

__tests__/delete-item.test.mts

+14-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as core from '@actions/core';
44

55
import * as index from '../src/delete-item.js';
66
import { ItemDetails, deleteItem, getItem } from '../src/lib.js';
7-
import { mockGetInput } from './utils.js';
7+
import { mockGetBooleanInput, mockGetInput } from './utils.js';
88

99
vi.mock('@actions/core');
1010
vi.mock('../src/lib');
@@ -51,6 +51,7 @@ describe('deleteItemAction', () => {
5151

5252
it('handles item not found', async () => {
5353
mockGetInput({ owner, 'project-number': projectNumber, item });
54+
mockGetBooleanInput({ 'fail-if-item-not-found': true });
5455
vi.mocked(deleteItem).mockResolvedValue();
5556

5657
await index.deleteItemAction();
@@ -60,6 +61,18 @@ describe('deleteItemAction', () => {
6061
expect(core.setFailed).toHaveBeenLastCalledWith(`Item not found: ${item}`);
6162
});
6263

64+
it('can ignore item not found', async () => {
65+
mockGetInput({ owner, 'project-number': projectNumber, item });
66+
mockGetBooleanInput({ 'fail-if-item-not-found': false });
67+
vi.mocked(getItem).mockResolvedValue(null);
68+
69+
await index.deleteItemAction();
70+
expect(deleteItemActionSpy).toHaveReturned();
71+
72+
expect(core.setFailed).not.toHaveBeenCalled();
73+
expect(core.setOutput).not.toHaveBeenCalled();
74+
});
75+
6376
it('handles project not found', async () => {
6477
mockGetInput({ owner, 'project-number': projectNumber, item });
6578
vi.mocked(getItem).mockResolvedValue({ id: itemId } as ItemDetails);

__tests__/edit-item.test.mts

+14-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as core from '@actions/core';
44

55
import * as index from '../src/edit-item.js';
66
import { ItemDetails, editItem, getItem } from '../src/lib.js';
7-
import { mockGetInput } from './utils.js';
7+
import { mockGetBooleanInput, mockGetInput } from './utils.js';
88

99
vi.mock('@actions/core');
1010
vi.mock('../src/lib');
@@ -86,6 +86,7 @@ describe('editItemAction', () => {
8686

8787
it('handles item not found', async () => {
8888
mockGetInput({ owner, 'project-number': projectNumber, item });
89+
mockGetBooleanInput({ 'fail-if-item-not-found': true });
8990
vi.mocked(editItem).mockResolvedValue(itemId);
9091

9192
await index.editItemAction();
@@ -95,6 +96,18 @@ describe('editItemAction', () => {
9596
expect(core.setFailed).toHaveBeenLastCalledWith(`Item not found: ${item}`);
9697
});
9798

99+
it('can ignore item not found', async () => {
100+
mockGetInput({ owner, 'project-number': projectNumber, item });
101+
mockGetBooleanInput({ 'fail-if-item-not-found': false });
102+
vi.mocked(getItem).mockResolvedValue(null);
103+
104+
await index.editItemAction();
105+
expect(editItemActionSpy).toHaveReturned();
106+
107+
expect(core.setFailed).not.toHaveBeenCalled();
108+
expect(core.setOutput).not.toHaveBeenCalled();
109+
});
110+
98111
it('handles project not found', async () => {
99112
mockGetInput({ owner, 'project-number': projectNumber, item });
100113
vi.mocked(getItem).mockResolvedValue({

__tests__/get-item.test.mts

+14-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as core from '@actions/core';
44

55
import * as index from '../src/get-item.js';
66
import { getItem } from '../src/lib.js';
7-
import { mockGetInput } from './utils.js';
7+
import { mockGetBooleanInput, mockGetInput } from './utils.js';
88

99
vi.mock('@actions/core');
1010
vi.mock('../src/lib');
@@ -52,6 +52,7 @@ describe('getItemAction', () => {
5252

5353
it('handles item not found', async () => {
5454
mockGetInput({ owner, 'project-number': projectNumber, item });
55+
mockGetBooleanInput({ 'fail-if-item-not-found': true });
5556
vi.mocked(getItem).mockResolvedValue(null);
5657

5758
await index.getItemAction();
@@ -61,6 +62,18 @@ describe('getItemAction', () => {
6162
expect(core.setFailed).toHaveBeenLastCalledWith(`Item not found: ${item}`);
6263
});
6364

65+
it('can ignore item not found', async () => {
66+
mockGetInput({ owner, 'project-number': projectNumber, item });
67+
mockGetBooleanInput({ 'fail-if-item-not-found': false });
68+
vi.mocked(getItem).mockResolvedValue(null);
69+
70+
await index.getItemAction();
71+
expect(getItemActionSpy).toHaveReturned();
72+
73+
expect(core.setFailed).not.toHaveBeenCalled();
74+
expect(core.setOutput).not.toHaveBeenCalled();
75+
});
76+
6477
it('handles project not found', async () => {
6578
mockGetInput({ owner, 'project-number': projectNumber, item });
6679
vi.mocked(getItem).mockImplementation(() => {

delete-item/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Can not delete archived items due to a bug in the GitHub GraphQL API, see <https
1616
| `owner` | The owner of the project - either an organization or a user. If not provided, it defaults to the repository owner. | No | `${{ github.repository_owner }}` |
1717
| `project-number` | The project number from the project's URL. | Yes | |
1818
| `item` | The item to delete - may be the global ID for the item, the content ID, or the content URL. | No | `${{ github.event.pull_request.html_url \|\| github.event.issue.html_url }}` |
19+
| `fail-if-item-not-found` | Should the action fail if the item is not found on the project | No | `true` |
1920

2021
## Outputs
2122

delete-item/action.yml

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ inputs:
1717
description: The item to delete - may be the global ID for the item, the content ID, or the content URL
1818
required: false
1919
default: ${{ github.event.pull_request.html_url || github.event.issue.html_url }}
20+
fail-if-item-not-found:
21+
description: Should the action fail if the item is not found on the project
22+
required: false
23+
default: true
2024

2125
runs:
2226
using: node20

dist/delete-item.js

+4-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/edit-item.js

+4-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/get-item.js

+4-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

edit-item/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Can not edit archived items due to a bug in the GitHub GraphQL API, see <https:/
2020
| `body` | Body for the item - can only be set for draft issues. | No | |
2121
| `field` | Project field to set on the item. | No | |
2222
| `field-value` | Value to set project field to. | No | |
23+
| `fail-if-item-not-found` | Should the action fail if the item is not found on the project | No | `true` |
2324

2425
## Outputs
2526

edit-item/action.yml

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ inputs:
2929
field-value:
3030
description: Value to set project field to
3131
required: false
32+
fail-if-item-not-found:
33+
description: Should the action fail if the item is not found on the project
34+
required: false
35+
default: true
3236

3337
outputs:
3438
id:

get-item/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Can not get archived items due to a bug in the GitHub GraphQL API, see <https://
1717
| `project-number` | The project number from the project's URL. | Yes | |
1818
| `item` | The item to get - may be the global ID for the item, the content ID, or the content URL. | No | `${{ github.event.pull_request.html_url \|\| github.event.issue.html_url }}` |
1919
| `field` | Project field to get on the item. | No | |
20+
| `fail-if-item-not-found` | Should the action fail if the item is not found on the project | No | `true` |
2021

2122
## Outputs
2223

get-item/action.yml

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ inputs:
2020
field:
2121
description: Project field to get on the item
2222
required: false
23+
fail-if-item-not-found:
24+
description: Should the action fail if the item is not found on the project
25+
required: false
26+
default: true
2327

2428
outputs:
2529
id:

src/delete-item.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ export async function deleteItemAction(): Promise<void> {
99
const projectNumber = core.getInput('project-number', { required: true });
1010
const item = core.getInput('item', { required: true });
1111

12+
// Optional inputs
13+
const failIfItemNotFound = core.getBooleanInput('fail-if-item-not-found');
14+
1215
// Item might be the item ID, the content ID, or the content URL
1316
const fullItem = await getItem(owner, projectNumber, item);
1417

1518
if (!fullItem) {
16-
core.setFailed(`Item not found: ${item}`);
19+
if (failIfItemNotFound) core.setFailed(`Item not found: ${item}`);
1720
return;
1821
}
1922

src/edit-item.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export async function editItemAction(): Promise<void> {
1414
const body = core.getInput('body');
1515
const field = core.getInput('field');
1616
const fieldValue = core.getInput('field-value', { required: !!field });
17+
const failIfItemNotFound = core.getBooleanInput('fail-if-item-not-found');
1718

1819
if (!!fieldValue && !field) {
1920
core.setFailed('Input required and not supplied: field');
@@ -24,7 +25,7 @@ export async function editItemAction(): Promise<void> {
2425
const fullItem = await getItem(owner, projectNumber, item);
2526

2627
if (!fullItem) {
27-
core.setFailed(`Item not found: ${item}`);
28+
if (failIfItemNotFound) core.setFailed(`Item not found: ${item}`);
2829
return;
2930
}
3031

src/get-item.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ export async function getItemAction(): Promise<void> {
1111

1212
// Optional inputs
1313
const field = core.getInput('field') || undefined;
14+
const failIfItemNotFound = core.getBooleanInput('fail-if-item-not-found');
1415

1516
// Item might be the item ID, the content ID, or the content URL
1617
const fullItem = await getItem(owner, projectNumber, item, field);
1718

1819
if (!fullItem) {
19-
core.setFailed(`Item not found: ${item}`);
20+
if (failIfItemNotFound) core.setFailed(`Item not found: ${item}`);
2021
return;
2122
}
2223

0 commit comments

Comments
 (0)