Skip to content

Commit

Permalink
feat(action): add possibility to delete a card from project (#56)
Browse files Browse the repository at this point in the history
Co-authored-by: Alex Page <alex@alexpage.com.au>
  • Loading branch information
jurijzahn8019 and Alex Page authored Dec 10, 2020
1 parent 10f3bf1 commit eb6c8c4
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 31 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Change these options in the workflow `.yml` file to meet your GitHub project nee
| `project` | The name of the project | `Backlog` |
| `column` | The column to create or move the card to | `Triage` |
| `repo-token` | The personal access token | `${{ secrets.GITHUB_TOKEN }}` |
| `action` | This determines the type of the action to be performed on the card, Default: `update` | `update`, `delete`, `archive` |

## Personal access token (secrets.GITHUB_TOKEN)

Expand Down Expand Up @@ -127,6 +128,7 @@ To set up the action for local development and testing:
## Release History
- v0.5.0 - Add option to `delete` card
- v0.4.0 - Add `issue_comment` event
- v0.3.0 - Add `pull_request_target` event
- v0.2.4 - Update dependencies
Expand Down
79 changes: 69 additions & 10 deletions __tests__/generate-mutation-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,21 @@ const moveData = {
};

test('generateMutationQuery move the card when in the correct project and wrong column', t => {
t.deepEqual(generateMutationQuery(moveData, project, column, nodeId), [
t.deepEqual(generateMutationQuery(moveData, project, column, nodeId, 'update'), [
`mutation {
moveProjectCard( input: {
cardId: "MDExOlByb2plY3RDYXJkMzUxNzI2MjM=",
columnId: "MDEzOlByb2plY3RDb2x1bW44NDU0MzQ5"
}) { clientMutationId } }`
moveProjectCard( input: {
cardId: "MDExOlByb2plY3RDYXJkMzUxNzI2MjM=",
columnId: "MDEzOlByb2plY3RDb2x1bW44NDU0MzQ5"
}) { clientMutationId } }`
]);
});

test('generateMutationQuery delete the card when it is in the project already', t => {
t.deepEqual(generateMutationQuery(moveData, project, column, nodeId, 'delete'), [
`mutation {
deleteProjectCard( input: {
cardId: "MDExOlByb2plY3RDYXJkMzUxNzI2MjM="
}) { clientMutationId } }`
]);
});

Expand Down Expand Up @@ -91,15 +100,65 @@ const addData = {
};

test('generateMutationQuery add the card when the card does not exist in the project', t => {
t.deepEqual(generateMutationQuery(addData, project, column, nodeId), [
t.deepEqual(generateMutationQuery(addData, project, column, nodeId, 'update'), [
`mutation {
addProjectCard( input: {
contentId: "MDU6SXNzdWU1ODc4NzU1Mjk=",
projectColumnId: "MDEzOlByb2plY3RDb2x1bW44NDU0MzQ5"
}) { clientMutationId } }`
addProjectCard( input: {
contentId: "MDU6SXNzdWU1ODc4NzU1Mjk=",
projectColumnId: "MDEzOlByb2plY3RDb2x1bW44NDU0MzQ5"
}) { clientMutationId } }`
]);
});

test('generateMutationQuery skip issue deletion when the card does not exist in the project', t => {
t.deepEqual(generateMutationQuery(addData, project, column, nodeId, 'delete'), []);
});

const archiveData = {
projectCards: {
nodes: [
{
id: 'MDExOlByb2plY3RDYXJkMzUxNzI2MjM=',
isArchived: true,
project: {
name: project,
id: 'MDc6UHJvamVjdDQwNzU5MDI='
}
}
]
},
repository: {
projects: {
nodes: [
{
name: project,
id: 'MDc6UHJvamVjdDQwNzU5MDI=',
columns: {
nodes: [
{
id: 'MDEzOlByb2plY3RDb2x1bW44NDU0MzQ5',
name: column
},
{
id: 'MDEzOlByb2plY3RDb2x1bW44MjUxOTAz',
name: 'In progress'
}
]
}
}
]
},
owner: {
projects: {
nodes: []
}
}
}
};

test('generateMutationQuery skip issue archive when the card is already archived', t => {
t.deepEqual(generateMutationQuery(archiveData, project, column, nodeId, 'archive'), []);
});

const dataNoColumn = {
projectCards: {
nodes: []
Expand Down
2 changes: 2 additions & 0 deletions __tests__/generate-project-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const issueQuery = `query {
projectCards {
nodes {
id
isArchived
project {
name
id
Expand Down Expand Up @@ -54,6 +55,7 @@ const pullrequestQuery = `query {
projectCards {
nodes {
id
isArchived
project {
name
id
Expand Down
6 changes: 6 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ inputs:
column:
description: 'The name of the column to move the issue or pull request to'
required: true
action:
description: |
Can be `update`, `delete` or `archive`. This determines the type of the action
to be performed on the card
required: false
default: "update"
runs:
using: 'node12'
main: 'dist/index.js'
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "github-project-automation-plus",
"version": "0.3.0",
"version": "0.5.0",
"description": "🤖 Automate GitHub Project cards with any webhook event",
"private": true,
"main": "dist/index.js",
Expand All @@ -11,7 +11,7 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/alex-page/automate-project-columns.git"
"url": "git+https://github.com/alex-page/github-project-automation-plus.git"
},
"keywords": [
"github-actions",
Expand All @@ -24,9 +24,9 @@
"author": "Alex Page <alex@alexpage.com.au>",
"license": "MIT",
"bugs": {
"url": "https://github.com/alex-page/automate-project-columns/issues"
"url": "https://github.com/alex-page/github-project-automation-plus/issues"
},
"homepage": "https://github.com/alex-page/automate-project-columns#readme",
"homepage": "https://github.com/alex-page/github-project-automation-plus#readme",
"dependencies": {
"@actions/core": "^1.2.3",
"@actions/github": "^2.1.1"
Expand Down
56 changes: 42 additions & 14 deletions src/generate-mutation-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
* @param {string} projectName - The user inputted project name
* @param {string} columnName - The user inputted column name
* @param {string} contentId - The id of the issue or pull request
* @param {"delete"|"archive"|"update"} action - the action to be performed on the card
*/
const generateMutationQuery = (data, projectName, columnName, contentId) => {
// if this is important, we will need to refactor the function
// eslint-disable-next-line max-params
const generateMutationQuery = (data, projectName, columnName, contentId, action) => {
// All the projects found in organisation and repositories
const repoProjects = data.repository.projects.nodes || [];
const orgProjects = (data.repository.owner &&
Expand Down Expand Up @@ -46,24 +49,49 @@ const generateMutationQuery = (data, projectName, columnName, contentId) => {

currentLocation.forEach(card => {
cardLocations[card.project.id].cardId = card.id;
cardLocations[card.project.id].isArchived = card.isArchived;
});

// If the card already exists in the project move it otherwise add a new card
const mutations = Object.keys(cardLocations).map(mutation => cardLocations[mutation].cardId ?
`mutation {
moveProjectCard( input: {
cardId: "${cardLocations[mutation].cardId}",
columnId: "${cardLocations[mutation].columnId}"
}) { clientMutationId } }` :
const mutations = Object.keys(cardLocations).map(mutation => {
if (action === 'update') {
// Othervise keep default procedure
return cardLocations[mutation].cardId ?
`mutation {
moveProjectCard( input: {
cardId: "${cardLocations[mutation].cardId}",
columnId: "${cardLocations[mutation].columnId}"
}) { clientMutationId } }` :

`mutation {
addProjectCard( input: {
contentId: "${contentId}",
projectColumnId: "${cardLocations[mutation].columnId}"
}) { clientMutationId } }`
);
`mutation {
addProjectCard( input: {
contentId: "${contentId}",
projectColumnId: "${cardLocations[mutation].columnId}"
}) { clientMutationId } }`;
}

return mutations;
if (action === 'delete' && cardLocations[mutation].cardId) {
// Delete issue from all boards, this if block
// prevents adding issue in case it has no card yet
return `mutation {
deleteProjectCard( input: {
cardId: "${cardLocations[mutation].cardId}"
}) { clientMutationId } }`;
}

if (action === 'archive' && !cardLocations[mutation].isArchived) {
// Archive issue if not already archived
return `mutation {
updateProjectCard(input: {
projectCardId: "${cardLocations[mutation].cardId}",
isArchived: true
}) { clientMutationId } }`;
}

return undefined;
});

return mutations.filter(m => m !== undefined);
};

module.exports = generateMutationQuery;
1 change: 1 addition & 0 deletions src/generate-project-query.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const projectQuery = (url, eventName, project) => (
projectCards {
nodes {
id
isArchived
project {
name
id
Expand Down
7 changes: 6 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const generateMutationQuery = require('./generate-mutation-query');
const token = core.getInput('repo-token');
const project = core.getInput('project');
const column = core.getInput('column');
const action = core.getInput('action') || 'update';

// Get data from the current action
const {eventName, nodeId, url} = getActionData(github.context);
Expand All @@ -27,7 +28,11 @@ const generateMutationQuery = require('./generate-mutation-query');
core.debug(JSON.stringify(resource));

// A list of columns that line up with the user entered project and column
const mutationQueries = generateMutationQuery(resource, project, column, nodeId);
const mutationQueries = generateMutationQuery(resource, project, column, nodeId, action);
if ((action === 'delete' || action === 'archive') && mutationQueries.length < 1) {
console.log('✅ There is nothing to do with card');
return;
}

core.debug(mutationQueries.join('\n'));

Expand Down

0 comments on commit eb6c8c4

Please sign in to comment.