From 8cef9b0d81b8e30632c2cf74fceed3d072a50b54 Mon Sep 17 00:00:00 2001 From: "willy.ovalle@klarna.com" Date: Wed, 31 Jul 2019 22:07:24 +0200 Subject: [PATCH 01/12] feat: adding support for regex in tickets --- lib/success.ts | 10 ++++++++-- lib/types.ts | 3 ++- lib/verifyConditions.ts | 23 +++++++++++++++++++---- test-config/package.json | 2 +- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/lib/success.ts b/lib/success.ts index 31b4098..f130bbe 100644 --- a/lib/success.ts +++ b/lib/success.ts @@ -6,10 +6,16 @@ import { GenerateNotesContext, PluginConfig } from './types'; import { escapeRegExp } from './util'; function getTickets(config: PluginConfig, context: GenerateNotesContext): string[] { - const patterns = config.ticketPrefixes! + let patterns: RegExp[] = []; + + if(config.ticketRegex) { + patterns = [new RegExp(config.ticketRegex, 'giu')]; + } else { + patterns = config.ticketPrefixes! .map(prefix => new RegExp(`\\b${escapeRegExp(prefix)}-(\\d+)\\b`, 'giu')); + } - const tickets = new Set(); + const tickets = new Set(); for (const commit of context.commits) { for (const pattern of patterns) { const matches = pattern.exec(commit.message); diff --git a/lib/types.ts b/lib/types.ts index 2fc084b..38bd367 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -56,7 +56,8 @@ export interface BaseConfig { } export interface PluginConfig extends BaseConfig { - ticketPrefixes: string[]; + ticketPrefixes?: string[]; + ticketRegex?: string; projectId: string; releaseNameTemplate?: string; jiraHost: string; diff --git a/lib/verifyConditions.ts b/lib/verifyConditions.ts index b248577..8692c3c 100644 --- a/lib/verifyConditions.ts +++ b/lib/verifyConditions.ts @@ -10,13 +10,28 @@ export async function verifyConditions(config: PluginConfig, context: PluginCont if (typeof config.projectId !== 'string') { throw new SemanticReleaseError(`config.projectId must be a string`); } - if (!Array.isArray(config.ticketPrefixes)) { - throw new SemanticReleaseError(`config.ticketPrefixes must be an array of string`); + + if (!config.ticketPrefixes && !config.ticketRegex) { + throw new SemanticReleaseError('Either config.ticketPrefixes or config.ticketRegex must be passed'); + } + + if (config.ticketPrefixes && config.ticketRegex) { + throw new SemanticReleaseError(`config.ticketPrefixes and config.ticketRegex cannot be passed at the same time`); } - for (const prefix of config.ticketPrefixes) { - if (typeof prefix !== 'string') { + + if (config.ticketPrefixes) { + if (!Array.isArray(config.ticketPrefixes)) { throw new SemanticReleaseError(`config.ticketPrefixes must be an array of string`); } + for (const prefix of config.ticketPrefixes) { + if (typeof prefix !== 'string') { + throw new SemanticReleaseError(`config.ticketPrefixes must be an array of string`); + } + } + } + + if (config.ticketRegex && typeof config.ticketRegex !== 'string') { + throw new SemanticReleaseError(`config.ticketRegex must be an string`); } if (config.releaseNameTemplate) { diff --git a/test-config/package.json b/test-config/package.json index ab3c98b..8873ad1 100644 --- a/test-config/package.json +++ b/test-config/package.json @@ -8,7 +8,7 @@ "@semantic-release/commit-analyzer": "^6.1.0", "@semantic-release/npm": "^5.1.4", "@semantic-release/release-notes-generator": "^7.1.4", - "semantic-release": "^15.13.3", + "semantic-release": "^15.13.3 || ^16.0.0", "semantic-release-jira-releases": "./.." } } From e1726fc1bb4302dd79919f1b6c4aab53cfd20274 Mon Sep 17 00:00:00 2001 From: "willy.ovalle@klarna.com" Date: Wed, 31 Jul 2019 22:18:27 +0200 Subject: [PATCH 02/12] docs: editing readme --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ffc4443..3de0e55 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,13 @@ The plugin should be added to your config "projectId": "UH", "releaseNameTemplate": "Test v${version}", "jiraHost": "uphabit.atlassian.net", - "ticketPrefixes": [ "TEST", "UH"] + "ticketPrefixes": [ "TEST", "UH"], + "ticketRegex": "[a-zA-Z]{3,5}-\d{3,5}" }] ] } + +Please note that `ticketRegex` cannot be used together with `ticketPrefixes`. ``` ```typescript interface Config { @@ -42,9 +45,13 @@ interface Config { /// A domain of a jira instance ie: `uphabit.atlasian.net` jiraHost: string; - // A list of prefixes to match when looking for tickets in commits + // A list of prefixes to match when looking for tickets in commits. Cannot be used together with ticketRegex. // ie. ['TEST'] would match `TEST-123` and `TEST-456` - ticketPrefixes: string[]; + ticketPrefixes?: string[]; + + // A regex to match tickets in commits (without slashes). Cannot be used together with ticketPrefixes. + // ie. [a-zA-Z]{4}-\d{3,5} would match any ticket with 3 letters a dash and 3 to 5 numbers, such as `TEST-456`, `TEST-5643` and `TEST-56432` + ticketRegex?: string; // The id or key for the project releases will be created in projectId: string; From e1bea7932f3c8ecd6647cadf6413500740137235 Mon Sep 17 00:00:00 2001 From: "willy.ovalle@klarna.com" Date: Wed, 31 Jul 2019 22:39:20 +0200 Subject: [PATCH 03/12] fix: escaping regex --- lib/success.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/success.ts b/lib/success.ts index f130bbe..deb1fb6 100644 --- a/lib/success.ts +++ b/lib/success.ts @@ -9,7 +9,7 @@ function getTickets(config: PluginConfig, context: GenerateNotesContext): string let patterns: RegExp[] = []; if(config.ticketRegex) { - patterns = [new RegExp(config.ticketRegex, 'giu')]; + patterns = [new RegExp(escapeRegExp(config.ticketRegex), 'giu')]; } else { patterns = config.ticketPrefixes! .map(prefix => new RegExp(`\\b${escapeRegExp(prefix)}-(\\d+)\\b`, 'giu')); From 96bc7276dde4707670492f45f0f7cdb722d2a7cd Mon Sep 17 00:00:00 2001 From: "willy.ovalle@klarna.com" Date: Wed, 31 Jul 2019 22:41:07 +0200 Subject: [PATCH 04/12] docs: adding regex unescaping --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3de0e55..a1dc5bd 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ The plugin should be added to your config "releaseNameTemplate": "Test v${version}", "jiraHost": "uphabit.atlassian.net", "ticketPrefixes": [ "TEST", "UH"], - "ticketRegex": "[a-zA-Z]{3,5}-\d{3,5}" + "ticketRegex": "[a-zA-Z]{3,5}-\\d{3,5}" }] ] } @@ -49,7 +49,7 @@ interface Config { // ie. ['TEST'] would match `TEST-123` and `TEST-456` ticketPrefixes?: string[]; - // A regex to match tickets in commits (without slashes). Cannot be used together with ticketPrefixes. + // A unescaped regex to match tickets in commits (without slashes). Cannot be used together with ticketPrefixes. // ie. [a-zA-Z]{4}-\d{3,5} would match any ticket with 3 letters a dash and 3 to 5 numbers, such as `TEST-456`, `TEST-5643` and `TEST-56432` ticketRegex?: string; From b69a06046a2ddb2a82b0f44a0ebb9ae0622b9077 Mon Sep 17 00:00:00 2001 From: "willy.ovalle@klarna.com" Date: Thu, 1 Aug 2019 10:09:41 +0200 Subject: [PATCH 05/12] chore: fixing whitespace --- lib/success.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/success.ts b/lib/success.ts index deb1fb6..4c5b044 100644 --- a/lib/success.ts +++ b/lib/success.ts @@ -8,7 +8,7 @@ import { escapeRegExp } from './util'; function getTickets(config: PluginConfig, context: GenerateNotesContext): string[] { let patterns: RegExp[] = []; - if(config.ticketRegex) { + if (config.ticketRegex) { patterns = [new RegExp(escapeRegExp(config.ticketRegex), 'giu')]; } else { patterns = config.ticketPrefixes! From 7a3957d5b14489ee7493f71f10f3e537f367b35e Mon Sep 17 00:00:00 2001 From: "willy.ovalle@klarna.com" Date: Thu, 15 Aug 2019 15:07:07 +0200 Subject: [PATCH 06/12] fix: fixing ticketRegex matching --- lib/success.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/success.ts b/lib/success.ts index 4c5b044..7f6d742 100644 --- a/lib/success.ts +++ b/lib/success.ts @@ -5,11 +5,11 @@ import { makeClient } from './jira'; import { GenerateNotesContext, PluginConfig } from './types'; import { escapeRegExp } from './util'; -function getTickets(config: PluginConfig, context: GenerateNotesContext): string[] { +export function getTickets(config: PluginConfig, context: GenerateNotesContext): string[] { let patterns: RegExp[] = []; - if (config.ticketRegex) { - patterns = [new RegExp(escapeRegExp(config.ticketRegex), 'giu')]; + if (config.ticketRegex !== undefined) { + patterns = [new RegExp(config.ticketRegex, 'giu')]; } else { patterns = config.ticketPrefixes! .map(prefix => new RegExp(`\\b${escapeRegExp(prefix)}-(\\d+)\\b`, 'giu')); @@ -18,7 +18,7 @@ function getTickets(config: PluginConfig, context: GenerateNotesContext): string const tickets = new Set(); for (const commit of context.commits) { for (const pattern of patterns) { - const matches = pattern.exec(commit.message); + const matches = commit.message.match(pattern); if (matches) { tickets.add(matches[0]); context.logger.info(`Found ticket ${matches[0]} in commit: ${commit.commit.short}`); From 9a503490aeb76291accc79bde1ebf40eb448d101 Mon Sep 17 00:00:00 2001 From: "willy.ovalle@klarna.com" Date: Thu, 15 Aug 2019 15:08:14 +0200 Subject: [PATCH 07/12] chore: adding initial tests for getTickets --- .travis.yml | 1 + babel.config.js | 6 ++++ package.json | 7 ++++- test/fakedata.ts | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ test/test.ts | 35 ++++++++++++++++++++++ 5 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 babel.config.js create mode 100644 test/fakedata.ts create mode 100644 test/test.ts diff --git a/.travis.yml b/.travis.yml index 5e51258..53460c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ script: # - shellcheck -x $(git ls-files | grep '[.]sh$') - ./node_modules/.bin/madge -c . - yarn audit + - yarn lint - yarn test before_deploy: diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..6b53630 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,6 @@ +module.exports = { + presets: [ + '@babel/preset-env', + '@babel/preset-typescript', + ], +}; \ No newline at end of file diff --git a/package.json b/package.json index 0b0b16d..57186cc 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "private": false, "scripts": { "prepublishOnly": "mkdir -p dist && rm -rf dist && tsc -p .", - "test": "tslint -p . && true \n#\n# No tests 😱\n#" + "lint": "tslint -p .", + "test": " yarn jest" }, "dependencies": { "@semantic-release/error": "^2.2.0", @@ -16,9 +17,13 @@ "tslib": "^1.9.2" }, "devDependencies": { + "@babel/preset-env": "^7.5.5", + "@babel/preset-typescript": "^7.3.3", + "@types/jest": "^24.0.17", "@types/lodash": "^4.14.120", "@types/node": "^10.12.19", "@types/signale": "^1.2.0", + "jest": "^24.8.0", "madge": "^3.4.3", "tslint": "^5.12.1", "tslint-config-airbnb": "^5.11.1", diff --git a/test/fakedata.ts b/test/fakedata.ts new file mode 100644 index 0000000..2b705bb --- /dev/null +++ b/test/fakedata.ts @@ -0,0 +1,76 @@ +import { BaseConfig, Person, Commit, PreviousRelease, UpcomingRelease, PluginConfig, PluginContext, GenerateNotesContext } from "../lib/types"; + +export const baseConfig: BaseConfig = { + $0: '', + branch: 'test', + debug: true, + dryRun: true, +} + +export const date = new Date("2019-01-01T00:00:00.000Z") + +export const author: Person = { + name: 'test', + email: 'email', + date, +} + +export const commits: Commit[] = [ + 'chore: fixing whitespace', + 'docs: adding regex unescaping', + 'fix: escaping regex', + 'docs: [FIX-321] editing readme', + 'feat: [UH-1258] better logging ', + 'feat: [UH-1258] Implement release creation', + 'fix: [FIX-123] typescript config', + 'fix: [TEST-123] test commit', +].map(m => ({ + author, + committer: author, + commitDate: date, + body: '', + hash: '', + message: m, + subject: '', + commit: { + long: '', + short: '' + } +})) + +export const previousRelease: PreviousRelease = { + gitHead: '', + gitTag: '', + version: '' +} + +export const upcomingRelease: UpcomingRelease = { + ...previousRelease, + notes: '', + type: '' +} + +export const pluginConfig: Partial = { + ...baseConfig, + projectId: 'TEST', + jiraHost: 'testjira.com' +} + +export const logger = { + info: jest.fn() +} + +export const pluginContext: PluginContext = { + cwd: '', + env: {}, + logger: logger as any, + options: baseConfig, + stderr: null, + stdout: null, +} +export const context: GenerateNotesContext = { + ...pluginContext, + commits, + lastRelease: previousRelease, + nextRelease: upcomingRelease +} \ No newline at end of file diff --git a/test/test.ts b/test/test.ts new file mode 100644 index 0000000..5550868 --- /dev/null +++ b/test/test.ts @@ -0,0 +1,35 @@ +import { getTickets } from "../lib/success"; +import { pluginConfig, context } from "./fakedata"; +import { PluginConfig } from "../lib/types"; + +describe('Success tests', () => { + describe('#getTickets', () => { + it('should analyze tickets with one ticketPrefix', () => { + const config = { + ...pluginConfig, + ticketPrefixes: ['UH'] + } as PluginConfig; + expect(getTickets(config, context)).toEqual(['UH-1258']) + }) + + it('should analyze tickets with many ticketPrefix', () => { + const config = { + ...pluginConfig, + ticketPrefixes: ['UH', 'FIX'] + } as PluginConfig + expect(getTickets(config, context)).toEqual(['FIX-321', 'UH-1258', 'FIX-123']) + }) + + it('should analyze tickets with ticketRegex', () => { + const ticketRegex = '[A-Za-z]+-\\d+'; + + const config: PluginConfig = { + ...pluginConfig, + ticketRegex + } as PluginConfig; + + expect(getTickets(config, context)).toEqual(['FIX-321', 'UH-1258', 'FIX-123', 'TEST-123']) + }) + }) +}) + From 90c992a9402c24ef44efe119bf0c9dd22d8a7e15 Mon Sep 17 00:00:00 2001 From: Gabriel Castro Date: Fri, 2 Aug 2019 09:39:59 -0400 Subject: [PATCH 08/12] add test-config to renovate --- renovate.json | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/renovate.json b/renovate.json index e27a038..2bbd383 100644 --- a/renovate.json +++ b/renovate.json @@ -1,16 +1,23 @@ { "extends": [ - "config:base" + "config:base", + ":preserveSemverRanges", + ":semanticCommitTypeAll(chore)" ], "docker": { "enabled": false }, + "packageRules": [ + { + "path": "./package.json" + }, + { + "path": "./test-config/package.json" + } + ], "rangeStrategy": "replace", "timezone": "America/Toronto", "rebaseStalePrs": true, "reviewers": ["GabrielCastro"], - "schedule": [ - "after 9am and before 3pm", - "every weekday" - ] + "schedule": ["after 9am and before 3pm", "every weekday"] } From 7253b62793b00e6389b027143902d1bc980356ee Mon Sep 17 00:00:00 2001 From: Gabriel Castro Date: Fri, 2 Aug 2019 09:41:32 -0400 Subject: [PATCH 09/12] [skip ci] update renovate config --- renovate.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renovate.json b/renovate.json index 2bbd383..168c902 100644 --- a/renovate.json +++ b/renovate.json @@ -9,10 +9,10 @@ }, "packageRules": [ { - "path": "./package.json" + "paths": ["./package.json"] }, { - "path": "./test-config/package.json" + "paths": ["./test-config/package.json"] } ], "rangeStrategy": "replace", From 05b883d5e18a804a276f80176709a73a05f20ff3 Mon Sep 17 00:00:00 2001 From: Gabriel Castro Date: Fri, 2 Aug 2019 09:46:02 -0400 Subject: [PATCH 10/12] fix(ci): make sure we can compile as a test --- package.json | 3 ++- yarn.lock | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 57186cc..d47eae3 100644 --- a/package.json +++ b/package.json @@ -8,11 +8,12 @@ "scripts": { "prepublishOnly": "mkdir -p dist && rm -rf dist && tsc -p .", "lint": "tslint -p .", + "build": "tsc -p .", "test": " yarn jest" }, "dependencies": { "@semantic-release/error": "^2.2.0", - "jira-connector": "^2.10.0", + "jira-connector": "^2.16.0", "lodash": "^4.17.11", "tslib": "^1.9.2" }, diff --git a/yarn.lock b/yarn.lock index d178954..b9bf437 100644 --- a/yarn.lock +++ b/yarn.lock @@ -674,10 +674,10 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -jira-connector@^2.10.0: - version "2.15.7" - resolved "https://registry.yarnpkg.com/jira-connector/-/jira-connector-2.15.7.tgz#fb1aee9f6a16df0f2b8a3c33057b42fdf977efe9" - integrity sha512-tv49hwAdgT4wOOb2j4vAHOQab7kIq0alWN9g0lq6tJgX4WEe/6FlX41x6A5G3TFE7n9JpUXXaJ17volagc2Jcw== +jira-connector@^2.16.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/jira-connector/-/jira-connector-2.16.0.tgz#1d811c01157574da6431bec4b0b93142ca7c296b" + integrity sha512-h4HYVYZ8Nbq8uiiCMuuY9Lm3sCi4SS1654GSvLS6nqF2/gFCWlmGx+5fEFAVODKXekjwuOUT3kDZpMzO1Uz6mw== dependencies: mime-types "^2.1.24" oauth "^0.9.12" From bfd2b781f81e929c8b3f1c37a1011b62a8ffe673 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 2 Aug 2019 13:51:03 +0000 Subject: [PATCH 11/12] chore(release): 0.2.1 [skip ci] ## [0.2.1](https://github.com/UpHabit/semantic-release-jira-releases/compare/v0.2.0...v0.2.1) (2019-08-02) ### Bug Fixes * **ci:** make sure we can compile as a test ([542429b](https://github.com/UpHabit/semantic-release-jira-releases/commit/542429b)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d3bcc4..fed990e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.2.1](https://github.com/UpHabit/semantic-release-jira-releases/compare/v0.2.0...v0.2.1) (2019-08-02) + + +### Bug Fixes + +* **ci:** make sure we can compile as a test ([542429b](https://github.com/UpHabit/semantic-release-jira-releases/commit/542429b)) + # [0.2.0](https://github.com/UpHabit/semantic-release-jira-releases/compare/v0.1.1...v0.2.0) (2019-07-22) diff --git a/package.json b/package.json index d47eae3..a75bd3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "semantic-release-jira-releases", - "version": "0.2.0", + "version": "0.2.1", "main": "dist/lib/index.js", "repository": "https://github.com/UpHabit/semantic-release-jira-releases", "license": "MIT", From 9bb2d51d726e081a45d653bee180a3aa8407cffa Mon Sep 17 00:00:00 2001 From: "willy.ovalle@klarna.com" Date: Thu, 15 Aug 2019 15:13:57 +0200 Subject: [PATCH 12/12] chore: adding build task after rebase --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 53460c2..ee2bc00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ script: # - shellcheck -x $(git ls-files | grep '[.]sh$') - ./node_modules/.bin/madge -c . - yarn audit + - yarn build - yarn lint - yarn test