forked from pagopa/io-app
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: [#177458092] Support Jira ticket key in the PR title (pagopa#2935
) * [#177458092] refactoring * [#177458092] wip * [#177458092] clean code * [#177458092] clean code * [#177458092] wip * [#177458092] integrate with existing code * [#177458092] fix * [#177458092] fix * [#177458092] read token from env * [#177458092] change username password concat * [#177458092] test remove checkDanger * [#177458092] test new danger * [#177458092] test * [#177458092] test * [#177458092] test * [#177458092] test url * [#177458092] add idprefix * [#177458092] fix * [#177458092] cannot use ?? operator * [#177458092] refactoring * [#177458092] fix ts * [#177458092] print failure * [#177458092] update error message * [#177458092] print also right if some right * [#177458092] test subtask * [#177458092] remove print * [#177458092] test * [#177458092] add italic * [#177458092] fix text * [#177458092] fix * [#177458092] feat: [FABT-1] test * feat: [FABT-1] test title chore: test chore: [FABT-1,FABT-3] This is a pr title bug: [FABT-7] this is a bug test . . . . . test test fix: [FABT-7] This is a fix feat: [#177458092] This is a pivotal story change func update jira regex * [#177458092] refactoring * [#177458092] Revert "[#177458092] refactoring" This reverts commit 1ef2a05. * [#177458092] refactoring * [#177458092] refactoring * [#177458092] refactoring * [#177458092] add comments * [#177458092] title uppercase * [#177458092] add tag * [#177458092] clean label * [#177458092] update label * [#177458092] refactoring * [#177458092] test * [#177458092] test uppercase * [#177458092] add comment * [#177458092] update comment * [#177458092] update text * Update scripts/ts/common/ticket/jira/index.ts Co-authored-by: Matteo Boschi <[email protected]> * [#177458092] use keyof instead of union Co-authored-by: Matteo Boschi <[email protected]>
- Loading branch information
1 parent
9b6a940
commit ff7601a
Showing
12 changed files
with
589 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,16 @@ | ||
// Import custom DangerJS rules. | ||
import { warn } from "danger"; | ||
// See http://danger.systems/js | ||
// See https://github.com/teamdigitale/danger-plugin-digitalcitizenship/ | ||
import checkDangers from "danger-plugin-digitalcitizenship"; | ||
import { DangerDSLType } from "danger/distribution/dsl/DangerDSL"; | ||
import {fromNullable, none} from "fp-ts/lib/Option"; | ||
import { | ||
allStoriesSameType, | ||
getChangelogPrefixByStories, | ||
getChangelogScope, | ||
getPivotalStoriesFromPrTitle | ||
} from "./scripts/changelog/ts/changelog"; | ||
import { commentPrWithTicketsInfo } from "./scripts/ts/danger/commentPrWithTicketsInfo"; | ||
import { updatePrTitleForChangelog } from "./scripts/ts/danger/updatePrTitleForChangelog"; | ||
import { getTicketsFromTitle } from "./scripts/ts/danger/utils/titleParser"; | ||
|
||
declare const danger: DangerDSLType; | ||
|
||
const multipleTypesWarning = | ||
"Multiple stories with different types are associated with this Pull request.\n" + | ||
"Only one tag will be added, following the order: `feature > bug > chore`"; | ||
|
||
/** | ||
* Append the changelog tag and scope to the pull request title | ||
*/ | ||
const updatePrTitleForChangelog = async () => { | ||
const associatedStories = await getPivotalStoriesFromPrTitle( | ||
danger.github.pr.title | ||
); | ||
|
||
if (!allStoriesSameType(associatedStories)) { | ||
warn(multipleTypesWarning); | ||
} | ||
const maybePrTag = getChangelogPrefixByStories(associatedStories); | ||
const eitherScope = getChangelogScope(associatedStories); | ||
|
||
if (eitherScope.isLeft()) { | ||
eitherScope.value.map(err => warn(err.message)); | ||
} | ||
const scope = eitherScope | ||
.getOrElse(none) | ||
.map(s => `(${s})`) | ||
.getOrElse(""); | ||
|
||
const cleanChangelogRegex = /^(fix(\(.+\))?!?: |feat(\(.+\))?!?: |chore(\(.+\))?!?: )?(.*)$/; | ||
const title = fromNullable(danger.github.pr.title.match(cleanChangelogRegex)) | ||
.map(matches => matches.pop() || danger.github.pr.title) | ||
.getOrElse(danger.github.pr.title); | ||
|
||
maybePrTag.map(tag => | ||
danger.github.api.pulls.update({ | ||
owner: danger.github.thisPR.owner, | ||
repo: danger.github.thisPR.repo, | ||
pull_number: danger.github.thisPR.number, | ||
title: `${tag}${scope}: ${title}` | ||
}) | ||
); | ||
const mainDanger = async () => { | ||
const associatedStories = await getTicketsFromTitle(danger.github.pr.title); | ||
commentPrWithTicketsInfo(associatedStories); | ||
await updatePrTitleForChangelog(associatedStories); | ||
}; | ||
|
||
checkDangers(); | ||
void updatePrTitleForChangelog() | ||
.then() | ||
.catch(); | ||
void mainDanger().then().catch(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { Either, toError } from "fp-ts/lib/Either"; | ||
import { TaskEither, tryCatch } from "fp-ts/lib/TaskEither"; | ||
import { Errors } from "io-ts"; | ||
import fetch from "node-fetch"; | ||
import { RemoteJiraTicket } from "./types"; | ||
|
||
const jiraOrgBaseUrl = "https://pagopa.atlassian.net/rest/api/3/issue/"; | ||
export const jiraTicketBaseUrl = "https://pagopa.atlassian.net/browse/"; | ||
const username = process.env.JIRA_USERNAME; | ||
const password = process.env.JIRA_PASSWORD; | ||
|
||
/** | ||
* Networking code to retrieve the remote representation for the JiraTicket | ||
* @param id | ||
*/ | ||
const retrieveRawJiraTicket = async (id: string): Promise<unknown> => { | ||
const url = new URL(id, jiraOrgBaseUrl); | ||
const res = await fetch(url, { | ||
method: "GET", | ||
headers: { | ||
Authorization: | ||
"Basic " + Buffer.from(`${username}:${password}`).toString("base64") | ||
} | ||
}); | ||
if (res.status !== 200) { | ||
throw new Error( | ||
`Response status ${res.status} ${res.statusText} for ${id}` | ||
); | ||
} | ||
return await res.json(); | ||
}; | ||
|
||
const retrieveRawJiraTicketTask = (id: string): TaskEither<Error, unknown> => | ||
tryCatch(() => retrieveRawJiraTicket(id), toError); | ||
|
||
/** | ||
* Ensure that the remote payload has the required fields | ||
* @param payload | ||
*/ | ||
const decodeRemoteJiraTicket = ( | ||
payload: any | ||
): Either<Errors, RemoteJiraTicket> => RemoteJiraTicket.decode(payload); | ||
|
||
const getJiraTicket = async ( | ||
jiraId: string | ||
): Promise<Either<Errors | Error, RemoteJiraTicket>> => | ||
( | ||
await retrieveRawJiraTicketTask(jiraId) | ||
.mapLeft<Errors | Error>(e => e) | ||
.run() | ||
).chain(decodeRemoteJiraTicket); | ||
|
||
/** | ||
* Retrieve {@link RemoteJiraTicket} using jiraIds as input | ||
* @param jiraIds | ||
*/ | ||
export const getJiraTickets = async ( | ||
jiraIds: ReadonlyArray<string> | ||
): Promise<ReadonlyArray<Either<Errors | Error, RemoteJiraTicket>>> => | ||
await Promise.all(jiraIds.map(getJiraTicket)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import * as t from "io-ts"; | ||
|
||
const JiraIssueType = t.keyof({ | ||
Epic: null, | ||
Story: null, | ||
Task: null, | ||
Sottotask: null, | ||
Bug: null | ||
}); | ||
|
||
export type JiraIssueType = t.TypeOf<typeof JiraIssueType>; | ||
|
||
const IssueType = t.interface({ | ||
name: JiraIssueType, | ||
subtask: t.boolean | ||
}); | ||
|
||
const Project = t.interface({ | ||
id: t.string, | ||
key: t.string, | ||
name: t.string | ||
}); | ||
|
||
const FieldsR = t.interface({ | ||
issuetype: IssueType, | ||
project: Project, | ||
labels: t.array(t.string), | ||
summary: t.string | ||
}); | ||
|
||
const FieldsP = t.partial({ | ||
parent: t.interface({ | ||
key: t.string, | ||
fields: t.interface({ | ||
summary: t.string, | ||
issuetype: IssueType | ||
}) | ||
}) | ||
}); | ||
|
||
const Fields = t.intersection([FieldsR, FieldsP], "Fields"); | ||
|
||
/** | ||
* The required fields from the remote response. | ||
* Not all the fields are used, see https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-get | ||
* for more information | ||
*/ | ||
export const RemoteJiraTicket = t.interface({ | ||
key: t.string, | ||
fields: Fields | ||
}); | ||
|
||
export type RemoteJiraTicket = t.TypeOf<typeof RemoteJiraTicket>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.