Skip to content

Commit f6ab71e

Browse files
committed
merge master into main
2 parents f1ab1fd + 0a1770e commit f6ab71e

9 files changed

Lines changed: 104 additions & 51 deletions

File tree

.github/workflows/ci.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ jobs:
5454
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
5555
permissions:
5656
contents: read
57-
issues: write
58-
pull-requests: write
5957
steps:
6058
- name: Checkout repository
6159
uses: actions/checkout@v4
@@ -71,14 +69,5 @@ jobs:
7169
- name: Install dependencies
7270
run: npm ci
7371

74-
- name: Validate release tokens are present
75-
run: |
76-
test -n "$GITHUB_TOKEN"
77-
test -n "$NPM_TOKEN"
78-
7972
- name: Run semantic-release in dry-run mode
80-
env:
81-
CI: true
82-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
83-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
8473
run: npm run release:dry-run

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# [1.6.0](https://github.com/oleg-koval/semantic-release-npm-github-publish/compare/v1.5.5...v1.6.0) (2026-04-04)
2+
3+
4+
### ✨ Features
5+
6+
* **release:** add beta channel and docs automation ([#56](https://github.com/oleg-koval/semantic-release-npm-github-publish/issues/56)) ([6610c1c](https://github.com/oleg-koval/semantic-release-npm-github-publish/commit/6610c1c7d18366638268d3ff17b84a97e7cec484))
7+
18
## [1.5.5](https://github.com/oleg-koval/semantic-release-npm-github-publish/compare/v1.5.4...v1.5.5) (2023-12-22)
29

310

commit-transform.js

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,59 +12,51 @@ const COMMIT_HASH_LENGTH = 7;
1212
* @return {Object} the transformed commit.
1313
*/
1414
module.exports = (commit, context) => {
15-
if (commit.notes) {
16-
commit.notes.forEach(note => {
17-
note.title = 'Breaking changes';
18-
});
19-
}
20-
21-
if (types.types[commit.type] && (types.types[commit.type].changelog || (commit.notes && commit.notes.length > 0))) {
22-
commit.groupType = `${types.types[commit.type].emoji ? `${types.types[commit.type].emoji} ` : ''}${
23-
types.types[commit.type].title
24-
}`;
25-
commit.type = commit.groupType;
26-
} else {
15+
const commitType = types.types[commit.type];
16+
const notes = Array.isArray(commit.notes)
17+
? commit.notes.map(note => ({
18+
...note,
19+
title: 'Breaking changes',
20+
}))
21+
: [];
22+
23+
if (!commitType || (!commitType.changelog && notes.length === 0)) {
2724
return null;
2825
}
2926

30-
if (commit.scope === '*') {
31-
commit.scope = '';
32-
}
33-
34-
if (typeof commit.hash === 'string') {
35-
commit.shortHash = commit.hash.slice(0, COMMIT_HASH_LENGTH);
36-
}
27+
const groupType = `${commitType.emoji ? `${commitType.emoji} ` : ''}${commitType.title}`;
3728

3829
const references = [];
30+
let subject = commit.subject;
3931

40-
if (typeof commit.subject === 'string') {
32+
if (typeof subject === 'string') {
4133
let url = context.repository ? `${context.host}/${context.owner}/${context.repository}` : context.repoUrl;
4234

4335
if (url) {
4436
url += '/issues/';
4537
// Issue URLs.
46-
commit.subject = commit.subject.replace(/#(\d+)/g, (_, issue) => {
38+
subject = subject.replace(/#(\d+)/g, (_, issue) => {
4739
references.push(issue);
4840
return `[#${issue}](${url}${issue})`;
4941
});
5042
}
5143

5244
if (context.host) {
5345
// User URLs.
54-
commit.subject = commit.subject.replace(/\B@([a-z0-9](?:-?[a-z0-9]){0,38})/g, `[@$1](${context.host}/$1)`);
46+
subject = subject.replace(/\B@([a-z0-9](?:-?[a-z0-9]){0,38})/g, `[@$1](${context.host}/$1)`);
5547
}
5648
}
5749

58-
if (commit.references) {
59-
// Remove references that already appear in the subject
60-
commit.references = commit.references.filter(reference => {
61-
if (!references.includes(reference.issue)) {
62-
return true;
63-
}
64-
65-
return false;
66-
});
67-
}
68-
69-
return commit;
50+
return {
51+
...commit,
52+
groupType,
53+
type: groupType,
54+
scope: commit.scope === '*' ? '' : commit.scope,
55+
shortHash: typeof commit.hash === 'string' ? commit.hash.slice(0, COMMIT_HASH_LENGTH) : commit.shortHash,
56+
subject,
57+
notes,
58+
references: Array.isArray(commit.references)
59+
? commit.references.filter(reference => !references.includes(reference.issue))
60+
: commit.references,
61+
};
7062
};

docs/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ Repository documentation kept in sync by `docs-index-keeper`.
44

55
| Doc | Purpose |
66
| --- | --- |
7-
| [release-channels.md](./release-channels.md) | Stable and beta release channel behavior for this repository |
8-
| [release-channels](release-channels.md) | Release Channels |
7+
| [release-channels.md](./release-channels.md) | Stable and beta release channel behavior for this repository |

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"scripts": {
6060
"docs:index:check": "docs-index-keeper check",
6161
"docs:index:update": "docs-index-keeper update",
62-
"release:dry-run": "semantic-release --dry-run --debug --extends ./release.repo.config.js",
62+
"release:dry-run": "node ./scripts/release-dry-run.mjs",
6363
"test": "node --test",
6464
"test:config": "node -e \"const config = require('./release.config.js'); if (!Array.isArray(config.plugins) || config.plugins.length === 0) { throw new Error('release config did not load plugins'); }\"",
6565
"semantic-release": "semantic-release --extends ./release.repo.config.js",
@@ -69,6 +69,6 @@
6969
"docsIndexKeeper": {
7070
"indexFile": "docs/README.md"
7171
},
72-
"version": "1.5.5",
72+
"version": "1.6.0",
7373
"snyk": true
7474
}

release.dry-run.config.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const repoConfig = require('./release.repo.config');
2+
3+
module.exports = {
4+
...repoConfig,
5+
plugins: [
6+
repoConfig.plugins[0],
7+
'@semantic-release/release-notes-generator',
8+
],
9+
};

scripts/release-dry-run.mjs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {createRequire} from 'node:module';
2+
3+
import semanticRelease from 'semantic-release';
4+
5+
const require = createRequire(import.meta.url);
6+
const config = require('../release.dry-run.config');
7+
8+
const result = await semanticRelease(
9+
{
10+
...config,
11+
ci: false,
12+
dryRun: true,
13+
},
14+
{
15+
cwd: process.cwd(),
16+
env: process.env,
17+
stderr: process.stderr,
18+
stdout: process.stdout,
19+
}
20+
);
21+
22+
if (!result) {
23+
console.log('[semantic-release] no release generated for the current branch');
24+
}

test/release-config.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const test = require('node:test');
66
const {analyzeCommits} = require('@semantic-release/commit-analyzer');
77

88
const transformCommit = require('../commit-transform');
9+
const dryRunReleaseConfig = require('../release.dry-run.config');
910
const releaseConfig = require('../release.config');
1011
const repoReleaseConfig = require('../release.repo.config');
1112

@@ -52,6 +53,16 @@ test('keeps beta prereleases as a repo-only branch policy', () => {
5253
]);
5354
});
5455

56+
test('uses auth-free plugins for release dry runs', () => {
57+
assert.deepEqual(
58+
dryRunReleaseConfig.plugins.map(plugin => Array.isArray(plugin) ? plugin[0] : plugin),
59+
[
60+
'@semantic-release/commit-analyzer',
61+
'@semantic-release/release-notes-generator',
62+
]
63+
);
64+
});
65+
5566
test('keeps standard feat/fix and breaking-change semantics', async () => {
5667
assert.equal(await analyzeReleaseType(['fix: correct output']), 'patch');
5768
assert.equal(await analyzeReleaseType(['feat: add publish summary']), 'minor');
@@ -91,6 +102,28 @@ test('formats changelog commit groups with curated titles', () => {
91102
);
92103
});
93104

105+
test('transforms immutable commit objects without mutating input', () => {
106+
const immutableCommit = Object.freeze({
107+
hash: '1234567890abcdef',
108+
notes: Object.freeze([Object.freeze({text: 'breaking'})]),
109+
references: Object.freeze([Object.freeze({issue: '42'})]),
110+
scope: '*',
111+
subject: 'add summary for #42',
112+
type: 'feat',
113+
});
114+
115+
const transformed = transformCommit(immutableCommit, {
116+
host: 'https://github.com',
117+
owner: 'oleg-koval',
118+
repository: 'semantic-release-npm-github-publish',
119+
});
120+
121+
assert.equal(transformed.scope, '');
122+
assert.equal(transformed.notes[0].title, 'Breaking changes');
123+
assert.equal(immutableCommit.notes[0].title, undefined);
124+
assert.equal(transformed.references.length, 0);
125+
});
126+
94127
test('drops unknown commit types from the changelog', () => {
95128
assert.equal(
96129
transformCommit(

0 commit comments

Comments
 (0)