diff --git a/README.md b/README.md index 4acb262a..702464d0 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,24 @@ # Attach to Trello Card action -The purpose of this action is to enable attaching a pull request to a Trello card, from within the PR body. This is best used with the Trello [Github Power-Up](https://trello.com/power-ups/55a5d916446f517774210004) added to your Trello Boards. With that enabled, this effectively enables the "Attach Pull Request" action of the Power-Up, but from the Github side (and via a quick URL copy-paste instead of clicking through menus). +The purpose of this action is to enable attaching a pull request to Trello cards, from within the PR body. This is best used with the Trello [Github Power-Up](https://trello.com/power-ups/55a5d916446f517774210004) added to your Trello Boards. With that enabled, this effectively enables the "Attach Pull Request" action of the Power-Up, but from the Github side (and via a quick URL copy-paste instead of clicking through menus). -The action looks for a Trello card URL at the start of a Pull Request description. If found, it will add the PR URL as an attachment to Trello. +The action looks for Trello card URLs at the start of a Pull Request description. If found, it will add the PR URL as an attachment to each specified card in Trello. -Optionally, this can be configured to also attach a (redundant) PR comment with link/name, similar to what the Trello Power-up will do, for use cases requiring that. +Optionally, this can be configured to also attach (redundant) PR comments with card links/names, similar to what the Trello Power-up will do, for use cases requiring that. + +## Link-Finding +URLs need to each be on own line (leading/trailing whitespace and extra blank lines don't matter), and be at top of PR body. URLs embedded in other text are ignored, as are URLs after descriptive (i.e., non-link) text starts. + +So, for : +```text +https://trello.com/c/aaaaaaaa + +https://trello.com/c/bbbbbbbbb +This PR impl's the above 2 features. These work similarly to feature https://trello.com/c/ccccccccc. +The below is a random trello url put in this body, for some reason: +https://trello.com/c/dddddddd +``` +only cards `aaaaaaaa` and `bbbbbbbbb` will have the PR attached. ## Events @@ -46,3 +60,8 @@ jobs: # repo-token: ${{ secrets.GITHUB_TOKEN }} ``` +## Development Notes +# Incrementing version +1. Update version in package.json (format should be `X.X.X`, per semver) +1. Commit/push changes +1. Create release (and publish to marketplace) - use 'v'-prepended format for new tag and release name \ No newline at end of file diff --git a/index.js b/index.js index 4df60e44..ac4d2fba 100644 --- a/index.js +++ b/index.js @@ -80,15 +80,33 @@ const addPrComment = async (body) => { }; -const extractTrelloCardId = (prBody) => { - core.debug(`pr body: ${prBody}`); +// to stop looking when we get to what looks like pr description, use stopOnNonLink true. to allow interspersed lines of +// yada yada yada b/w Trello links, use false. +const extractTrelloCardIds = (prBody, stopOnNonLink = true) => { + core.debug(`prBody: ${util.inspect(prBody)}`); - //find 1st instance of trello card url - must be 1st thing in PR - const matches = /^\s*https\:\/\/trello\.com\/c\/(\w+)/.exec(prBody); - const cardId = matches && matches[1]; - core.debug(`card id = ${cardId}`); - - return cardId; + // browsers submit textareas with \r\n line breaks on all platforms + const browserEol = '\r\n'; + // requires that link be alone own line, and allows leading/trailing whitespace + const linkRegex = /^\s*(https\:\/\/trello\.com\/c\/(\w+)\/\S+)?\s*$/; + + const cardIds = []; + const lines = prBody.split(browserEol); + + //loop and gather up cardIds, skipping blank lines. stopOnNonLink == true will bust out when we're out of link-only territory. + for(const line of lines) { + const matches = linkRegex.exec(line); + if(matches) { + if(matches[2]) { + core.debug(`found id ${matches[2]}`); + cardIds.push(matches[2]); + } + } else if(stopOnNonLink) { + core.debug('matched something non-blank/link. stopping search'); + break; + } + }; + return cardIds; } const commentsContainsTrelloLink = async (cardId) => { @@ -111,36 +129,39 @@ const buildTrelloLinkComment = async (cardId) => { return; } - const cardId = extractTrelloCardId(evthookPayload.pull_request.body); const prUrl = evthookPayload.pull_request.html_url; + const cardIds = extractTrelloCardIds(evthookPayload.pull_request.body); - if(cardId) { - let extantAttachments; + if(cardIds && cardIds.length > 0) { + for(const cardId of cardIds) { + let extantAttachments; - core.debug(`card url for ${cardId} specified in pr comment.`); - extantAttachments = await getCardAttachments(cardId); - - //make sure not already attached - if(extantAttachments == null || !extantAttachments.some(it => it.url === prUrl)) { - const createdAttachment = await createCardAttachment(cardId, prUrl); - core.info(`created trello attachment.`); - core.debug(util.inspect(createdAttachment)); + core.info(`card url for ${cardId} specified in pr.`); + extantAttachments = await getCardAttachments(cardId); + + //make sure not already attached + if(extantAttachments == null || !extantAttachments.some(it => it.url === prUrl)) { + const createdAttachment = await createCardAttachment(cardId, prUrl); + core.info(`created trello attachment for card ${cardId}.`); + core.debug(util.inspect(createdAttachment)); - // BRH NOTE actually, the power-up doesn't check if it previously added comment, so check is maybe superfluous - if(shouldAddPrComment && !await commentsContainsTrelloLink(cardId)) { - core.debug('adding pr comment'); - const newComment = await buildTrelloLinkComment(cardId) - - //comments as 'github actions' bot, at least when using token automatically generated for GH workflows - await addPrComment(newComment); + // BRH NOTE actually, the power-up doesn't check if it previously added comment, so this doesn't exactly match + // its fxnality. + if(shouldAddPrComment && !await commentsContainsTrelloLink(cardId)) { + core.debug(`adding pr comment for card ${cardId}.`); + const newComment = await buildTrelloLinkComment(cardId) + + //comments as 'github actions' bot, at least when using token automatically generated for GH workflows + await addPrComment(newComment); + } else { + core.info(`pr comment already present or unwanted for card ${cardId} - skipped comment add.`); + } } else { - core.info('pr comment already present or unwanted - skipped comment add.'); + core.info(`trello attachment for card ${cardId} already exists - skipped attachment create.`); } - } else { - core.info('trello attachement already exists - skipped create.'); - } + }; } else { - core.info(`no card url in pr comment. nothing to do.`); + core.info(`no card urls in pr comment. nothing to do.`); } } catch (error) { core.error(util.inspect(error)); diff --git a/package.json b/package.json index 53b1d7e7..c982d336 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "attach-to-trello-card-action", - "version": "1.0.0", + "version": "2.0.0", "description": "Github Action: Add attachment to a given Trello card URL (e.g., pull request)", "main": "index.js", "scripts": {