Skip to content

Commit

Permalink
feat: adding the ability to pass a regex to filter tickets (aechweeks#10
Browse files Browse the repository at this point in the history
)

feat: adding the ability to pass a regex to filter tickets
  • Loading branch information
GabrielCastro authored Aug 15, 2019
2 parents 3e80fa7 + caf25a0 commit 71b535f
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 13 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ script:
# - shellcheck -x $(git ls-files | grep '[.]sh$')
- ./node_modules/.bin/madge -c .
- yarn audit
- yarn build
- yarn lint
- yarn test

before_deploy:
Expand Down
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,27 @@ 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 {

/// 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 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;

// The id or key for the project releases will be created in
projectId: string;
Expand Down
6 changes: 6 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-typescript',
],
};
12 changes: 9 additions & 3 deletions lib/success.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ import { makeClient } from './jira';
import { GenerateNotesContext, PluginConfig } from './types';
import { escapeRegExp } from './util';

function getTickets(config: PluginConfig, context: GenerateNotesContext): string[] {
const patterns = config.ticketPrefixes!
export function getTickets(config: PluginConfig, context: GenerateNotesContext): string[] {
let patterns: RegExp[] = [];

if (config.ticketRegex !== undefined) {
patterns = [new RegExp(config.ticketRegex, 'giu')];
} else {
patterns = config.ticketPrefixes!
.map(prefix => new RegExp(`\\b${escapeRegExp(prefix)}-(\\d+)\\b`, 'giu'));
}

const tickets = new Set<string>();
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}`);
Expand Down
3 changes: 2 additions & 1 deletion lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export interface BaseConfig {
}

export interface PluginConfig extends BaseConfig {
ticketPrefixes: string[];
ticketPrefixes?: string[];
ticketRegex?: string;
projectId: string;
releaseNameTemplate?: string;
jiraHost: string;
Expand Down
23 changes: 19 additions & 4 deletions lib/verifyConditions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
"private": false,
"scripts": {
"prepublishOnly": "mkdir -p dist && rm -rf dist && tsc -p .",
"test": "tsc -p . && tslint -p . && true \n#\n# No tests 😱\n#"
"lint": "tslint -p .",
"build": "tsc -p .",
"test": " yarn jest"
},
"dependencies": {
"@semantic-release/error": "^2.2.0",
Expand All @@ -16,9 +18,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",
Expand Down
2 changes: 1 addition & 1 deletion test-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "./.."
}
}
76 changes: 76 additions & 0 deletions test/fakedata.ts
Original file line number Diff line number Diff line change
@@ -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<PluginConfig> = {
...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
}
35 changes: 35 additions & 0 deletions test/test.ts
Original file line number Diff line number Diff line change
@@ -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'])
})
})
})

0 comments on commit 71b535f

Please sign in to comment.