Skip to content

Commit dcc03d7

Browse files
authored
Merge pull request #1 from klerick/semantic-executer
feat(sevrel): add builder for semver publish
2 parents c3341ad + 4389a28 commit dcc03d7

24 files changed

+1851
-31
lines changed

.eslintrc.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
"jest": true
3838
},
3939
"rules": {}
40+
},
41+
{
42+
"files": "*.json",
43+
"parser": "jsonc-eslint-parser",
44+
"rules": {}
4045
}
4146
]
4247
}

libs/json-api-nestjs/project.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,6 @@
7373
}
7474
}
7575
},
76-
"tags": []
76+
"tags": [],
77+
"implicitDependencies": ["sevrel"]
7778
}

libs/sevrel/.eslintrc.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"extends": ["../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {}
8+
},
9+
{
10+
"files": ["*.ts", "*.tsx"],
11+
"rules": {}
12+
},
13+
{
14+
"files": ["*.js", "*.jsx"],
15+
"rules": {}
16+
},
17+
{
18+
"files": ["./package.json", "./generators.json", "./executors.json"],
19+
"parser": "jsonc-eslint-parser",
20+
"rules": {
21+
"@nrwl/nx/nx-plugin-checks": "error"
22+
}
23+
}
24+
]
25+
}

libs/sevrel/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# sevrel
2+
3+
This library was generated with [Nx](https://nx.dev).
4+
5+
## Building
6+
7+
Run `nx build sevrel` to build the library.
8+
9+
## Running unit tests
10+
11+
Run `nx test sevrel` to execute the unit tests via [Jest](https://jestjs.io).

libs/sevrel/builders.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"$schema": "http://json-schema.org/schema",
3+
"builders": {
4+
"release": {
5+
"implementation": "./src/builders/release/executor",
6+
"schema": "./src/builders/release/schema.json",
7+
"description": "release builders"
8+
}
9+
}
10+
}

libs/sevrel/jest.config.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: 'sevrel',
4+
preset: '../../jest.preset.js',
5+
globals: {
6+
'ts-jest': {
7+
tsconfig: '<rootDir>/tsconfig.spec.json',
8+
},
9+
},
10+
transform: {
11+
'^.+\\.[tj]s$': 'ts-jest',
12+
},
13+
moduleFileExtensions: ['ts', 'js', 'html'],
14+
coverageDirectory: '../../coverage/libs/sevrel',
15+
};

libs/sevrel/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "@nestjs-json-api/sevrel",
3+
"version": "0.0.1",
4+
"main": "src/index.js",
5+
"builders": "./builders.json"
6+
}

libs/sevrel/project.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"name": "sevrel",
3+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "libs/sevrel/src",
5+
"projectType": "library",
6+
"targets": {
7+
"build": {
8+
"executor": "@nrwl/js:tsc",
9+
"outputs": ["{options.outputPath}"],
10+
"options": {
11+
"outputPath": "dist/libs/sevrel",
12+
"main": "libs/sevrel/src/index.ts",
13+
"tsConfig": "libs/sevrel/tsconfig.lib.json",
14+
"assets": [
15+
"libs/sevrel/*.md",
16+
{
17+
"input": "./libs/sevrel/src",
18+
"glob": "**/!(*.ts)",
19+
"output": "./src"
20+
},
21+
{
22+
"input": "./libs/sevrel/src",
23+
"glob": "**/*.d.ts",
24+
"output": "./src"
25+
},
26+
{
27+
"input": "./libs/sevrel",
28+
"glob": "builders.json",
29+
"output": "."
30+
}
31+
]
32+
}
33+
},
34+
"lint": {
35+
"executor": "@nrwl/linter:eslint",
36+
"outputs": ["{options.outputFile}"],
37+
"options": {
38+
"lintFilePatterns": [
39+
"libs/sevrel/**/*.ts",
40+
"libs/sevrel/generators.json",
41+
"libs/sevrel/executors.json",
42+
"libs/sevrel/package.json"
43+
]
44+
}
45+
},
46+
"test": {
47+
"executor": "@nrwl/jest:jest",
48+
"outputs": ["coverage/libs/sevrel"],
49+
"options": {
50+
"jestConfig": "libs/sevrel/jest.config.ts",
51+
"passWithNoTests": true
52+
}
53+
}
54+
},
55+
"tags": []
56+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { PluginSpec } from 'semantic-release';
2+
3+
export function commitAnalyzer({ project }: { project: string }): PluginSpec {
4+
return [
5+
'@semantic-release/commit-analyzer',
6+
{
7+
parserOpts: {
8+
headerPattern: new RegExp(`^(\\w*)(?:\\((${project})\\))?: (.*)$`),
9+
},
10+
},
11+
];
12+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { BuilderContext, createBuilder } from '@angular-devkit/architect';
2+
import semanticRelease from 'semantic-release';
3+
4+
import { ReleaseExecutorSchema } from './schema';
5+
import { releaseNotesGenerator } from './release-notes-generator';
6+
import { commitAnalyzer } from './commit-analyzer';
7+
import { npm } from './npm';
8+
import { plugins } from './plugins';
9+
// import { preparePlugin } from './prepare';
10+
import { platformPlugin } from './platform-plugin';
11+
12+
async function runRelease(
13+
options: ReleaseExecutorSchema,
14+
builderContext: BuilderContext
15+
) {
16+
const {
17+
npm: { pkgRoot },
18+
dryRun,
19+
publishable,
20+
branches,
21+
} = options;
22+
23+
const { project } = builderContext.target;
24+
25+
const { outputPath } = await builderContext
26+
.getTargetOptions({
27+
project,
28+
target: 'build',
29+
})
30+
.catch(() => ({ outputPath: null }));
31+
32+
const publishPath = outputPath ?? pkgRoot;
33+
34+
if (publishable && !publishPath) {
35+
return {
36+
success: false,
37+
error: `Builder can't detect output path for the '${project}' project automatically. Please, provide the 'npm.pkgRoot' option`,
38+
};
39+
} else if (publishable) {
40+
builderContext.logger.info(
41+
`The directory ${publishPath} will be used for publishing`
42+
);
43+
}
44+
45+
return semanticRelease(
46+
{
47+
tagFormat: `${project}@\${version}`,
48+
branches,
49+
extends: undefined,
50+
dryRun,
51+
plugins: plugins([
52+
// preparePlugin({ publishable, publishPath }),
53+
commitAnalyzer({ project }),
54+
releaseNotesGenerator({ project }),
55+
npm({ publishable, publishPath }),
56+
platformPlugin(options, builderContext),
57+
]),
58+
},
59+
{
60+
env: { ...process.env },
61+
cwd: '.',
62+
}
63+
)
64+
.then((result) => {
65+
if (result) {
66+
const {
67+
nextRelease: { version },
68+
} = result;
69+
70+
builderContext.logger.info(
71+
`The '${project}' project released with version ${version}`
72+
);
73+
} else {
74+
builderContext.logger.info(
75+
`No new release for the '${project}' project`
76+
);
77+
}
78+
79+
return { success: true };
80+
})
81+
.catch((err) => {
82+
builderContext.logger.error(err);
83+
84+
return {
85+
success: false,
86+
error: `The automated release failed with error: ${err}`,
87+
};
88+
});
89+
}
90+
91+
export const SemrelBuilder = createBuilder(runRelease);
92+
93+
export default SemrelBuilder;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { PluginSpec } from 'semantic-release';
2+
3+
export function npm({
4+
publishable,
5+
publishPath
6+
}: {
7+
publishable: boolean;
8+
publishPath: string;
9+
}): PluginSpec | null {
10+
return publishable
11+
? ['@semantic-release/npm', { pkgRoot: publishPath }]
12+
: null;
13+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { ReleaseExecutorSchema } from './schema';
2+
import { BuilderContext } from '@angular-devkit/architect';
3+
import { PluginSpec } from 'semantic-release';
4+
import { isObject } from 'util';
5+
6+
const GITLAB_PACKAGE_NAME = '@semantic-release/gitlab';
7+
const GITHUB_PACKAGE_NAME = '@semantic-release/github';
8+
9+
export function platformPlugin(
10+
{ gitlab }: ReleaseExecutorSchema,
11+
builderContext: BuilderContext
12+
): PluginSpec {
13+
if (gitlab === true) {
14+
return GITLAB_PACKAGE_NAME;
15+
}
16+
17+
if (gitlab && isObject(gitlab)) {
18+
return [GITLAB_PACKAGE_NAME, gitlab];
19+
}
20+
21+
return [
22+
GITHUB_PACKAGE_NAME,
23+
{
24+
successComment: `:tada: This \${issue.pull_request ? 'pull request' : 'issue'} is included in version ${builderContext.target.project}@\${nextRelease.version} :tada:
25+
26+
The release is available on [GitHub release](<github_release_url>)`,
27+
releasedLabels: [
28+
`released<%= nextRelease.channel ? " on @\${nextRelease.channel}" : "" %>`,
29+
builderContext.target.project,
30+
],
31+
},
32+
];
33+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { PluginSpec } from 'semantic-release';
2+
3+
export function plugins(pluginSpecs: (PluginSpec | null)[]): PluginSpec[] {
4+
return pluginSpecs.filter(plugin => !!plugin);
5+
}

0 commit comments

Comments
 (0)