Skip to content

Commit 8b8b1ca

Browse files
authored
fix: generate correct changelogs when doing a PR (#113)
1 parent e36c455 commit 8b8b1ca

File tree

3 files changed

+151
-89
lines changed

3 files changed

+151
-89
lines changed

scripts/changelog.mjs

Lines changed: 36 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,20 @@
11
#!/usr/bin/env node
2-
import addStream from 'add-stream';
3-
import chalk from 'chalk';
4-
import conventionalChangelog from 'conventional-changelog';
52
import fs from 'node:fs';
6-
import path from 'node:path';
7-
import tempfile from 'tempfile';
3+
import { Package } from './changelog/Package.mjs';
4+
import { generateChangelog } from './changelog/generate.mjs';
85

96
const PRESET = 'angular';
107

118
/**
12-
* @typedef {{
13-
* path: string;
14-
* excluded?: true;
15-
* sameAs?: string;
16-
* name?: string;
17-
* changelogPath?: string;
18-
* version?: string;
19-
* gitPath?: string;
20-
* }} Package
21-
*
22-
* @type {Package[]}
9+
* @type {import('./changelog/Package.mjs').PackageConfiguration[]}
2310
*/
2411
const PACKAGES = [
2512
{ path: './packages/astro' },
2613
{ path: './packages/cli' },
2714
{ path: './packages/components/react' },
2815
{ path: './packages/runtime' },
16+
{ path: './packages/theme' },
17+
{ path: './packages/types' },
2918

3019
// we do not include this one because it is not published
3120
{ path: './packages/template', excluded: true },
@@ -37,98 +26,56 @@ const PACKAGES = [
3726
processPackages();
3827

3928
async function processPackages() {
29+
/** @type {Map<string, Package>} */
30+
const packages = new Map();
31+
4032
// infer extra properties
41-
for (const pkg of PACKAGES) {
42-
pkg.path = path.normalize(pkg.path);
33+
for (const pkgDef of PACKAGES) {
34+
const pkg = new Package(pkgDef);
35+
packages.set(pkg.name, pkg);
36+
}
4337

44-
const pkgJSON = JSON.parse(fs.readFileSync(path.join(pkg.path, 'package.json')));
38+
// overwrites temporarily the version on the `tutorialkit` package as it's released separately later
39+
const tutorialkit = packages.get('tutorialkit');
40+
const tutorialkitAstro = packages.get('@tutorialkit/astro');
4541

46-
pkg.name = pkgJSON.name;
47-
pkg.version = pkgJSON.version;
48-
pkg.changelogPath = path.join(pkg.path, 'CHANGELOG.md');
49-
}
42+
const originalVersion = tutorialkit.version;
43+
tutorialkit.version = tutorialkitAstro.version;
44+
45+
tutorialkit.write();
5046

5147
// generate change logs
5248
await Promise.all(
53-
PACKAGES.map((pkg) => {
49+
[...packages.values()].map((pkg) => {
5450
if (pkg.excluded) {
55-
return;
51+
return Promise.resolve();
5652
}
5753

58-
return generateChangelog(pkg);
54+
return generateChangelog(pkg, PRESET);
5955
}),
6056
);
6157

6258
// copy changelogs that are identical
63-
for (const pkg of PACKAGES) {
59+
for (const pkg of packages.values()) {
6460
if (pkg.sameAs) {
65-
const otherPkg = PACKAGES.find((otherPkg) => otherPkg.name === pkg.sameAs);
61+
const otherPkg = packages.get(pkg.sameAs);
6662

6763
fs.copyFileSync(otherPkg.changelogPath, pkg.changelogPath);
6864
}
6965
}
7066

7167
// generate root changelog
72-
const tutorialkit = PACKAGES.find((pkg) => pkg.name === 'tutorialkit');
73-
74-
await generateChangelog({
75-
version: tutorialkit.version,
76-
path: tutorialkit.path,
77-
gitPath: '.',
78-
changelogPath: 'CHANGELOG.md',
79-
});
80-
}
81-
82-
/**
83-
* Generate a changelog for the provided package and aggregate the data
84-
* for the root changelog.
85-
*
86-
* @param {Package} pkg the package
87-
*/
88-
function generateChangelog(pkg) {
89-
const options = {
90-
preset: PRESET,
91-
pkg: {
92-
path: pkg.path,
68+
await generateChangelog(
69+
{
70+
version: tutorialkit.version,
71+
path: tutorialkit.path,
72+
gitPath: '.',
73+
changelogPath: 'CHANGELOG.md',
9374
},
94-
append: undefined,
95-
releaseCount: undefined,
96-
skipUnstable: undefined,
97-
outputUnreleased: undefined,
98-
tagPrefix: undefined,
99-
};
100-
101-
const context = {
102-
version: pkg.version,
103-
title: pkg.name,
104-
};
105-
106-
const gitRawCommitsOpts = {
107-
path: pkg.gitPath ?? pkg.path,
108-
};
109-
110-
const changelogStream = conventionalChangelog(options, context, gitRawCommitsOpts).on('error', (error) => {
111-
console.error(error.stack);
112-
process.exit(1);
113-
});
114-
115-
const CHANGELOG_FILE = pkg.changelogPath;
116-
117-
return new Promise((resolve) => {
118-
const readStream = fs.createReadStream(CHANGELOG_FILE).on('error', () => {
119-
// if there was no changelog we create it here
120-
changelogStream.pipe(fs.createWriteStream(CHANGELOG_FILE)).on('finish', resolve);
121-
});
122-
123-
const tmp = tempfile();
124-
125-
changelogStream
126-
.pipe(addStream(readStream))
127-
.pipe(fs.createWriteStream(tmp))
128-
.on('finish', () => {
129-
fs.createReadStream(tmp).pipe(fs.createWriteStream(CHANGELOG_FILE)).on('finish', resolve);
130-
});
131-
}).then(() => {
132-
console.log(`${chalk.green('UPDATED')} ${CHANGELOG_FILE} ${chalk.gray(pkg.version)}`);
133-
});
75+
PRESET,
76+
);
77+
78+
// reset the version of the CLI:
79+
tutorialkit.version = originalVersion;
80+
tutorialkit.write();
13481
}

scripts/changelog/Package.mjs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
4+
/**
5+
* @typedef {{
6+
* path: string;
7+
* excluded?: true;
8+
* sameAs?: string;
9+
* }} PackageConfiguration A package in the monorepo to generate changelog for.
10+
*/
11+
12+
export class Package {
13+
/**
14+
* @param {PackageConfiguration} pkg
15+
*/
16+
constructor(pkg) {
17+
const pkgPath = path.normalize(pkg.path);
18+
const pkgJSON = JSON.parse(fs.readFileSync(path.join(pkgPath, 'package.json')));
19+
20+
this.excluded = pkg.excluded;
21+
this.path = pkgPath;
22+
this.pkgJSON = pkgJSON;
23+
this.changelogPath = path.join(pkgPath, 'CHANGELOG.md');
24+
}
25+
26+
write() {
27+
fs.writeFileSync(path.join(this.path, 'package.json'), JSON.stringify(this.pkgJSON, undefined, 2) + '\n', 'utf-8');
28+
}
29+
30+
get name() {
31+
return this.pkgJSON.name;
32+
}
33+
34+
set name(value) {
35+
this.pkgJSON.name = value;
36+
}
37+
38+
get version() {
39+
return this.pkgJSON.version;
40+
}
41+
42+
set version(value) {
43+
this.pkgJSON.version = value;
44+
}
45+
}

scripts/changelog/generate.mjs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import fs from 'node:fs';
2+
import addStream from 'add-stream';
3+
import chalk from 'chalk';
4+
import conventionalChangelog from 'conventional-changelog';
5+
import tempfile from 'tempfile';
6+
7+
/**
8+
* @typedef {{
9+
* path: string;
10+
* gitPath?: string;
11+
* version: string;
12+
* name: string;
13+
* changelogPath: string;
14+
* }} PackageSpec A package specification to generate the changelog from.
15+
*/
16+
17+
/**
18+
* Generate a changelog for the provided package and aggregate the data
19+
* for the root changelog.
20+
*
21+
* @param {PackageSpec} pkg the package
22+
* @param {string} preset preset to use
23+
*/
24+
export function generateChangelog(pkg, preset) {
25+
const options = {
26+
preset,
27+
pkg: {
28+
path: pkg.path,
29+
},
30+
append: undefined,
31+
releaseCount: undefined,
32+
skipUnstable: undefined,
33+
outputUnreleased: undefined,
34+
tagPrefix: undefined,
35+
};
36+
37+
const context = {
38+
version: pkg.version,
39+
title: pkg.name,
40+
};
41+
42+
const gitRawCommitsOpts = {
43+
path: pkg.gitPath ?? pkg.path,
44+
};
45+
46+
const changelogStream = conventionalChangelog(options, context, gitRawCommitsOpts).on('error', (error) => {
47+
console.error(error.stack);
48+
process.exit(1);
49+
});
50+
51+
const CHANGELOG_FILE = pkg.changelogPath;
52+
53+
return new Promise((resolve) => {
54+
const readStream = fs.createReadStream(CHANGELOG_FILE).on('error', () => {
55+
// if there was no changelog we create it here
56+
changelogStream.pipe(fs.createWriteStream(CHANGELOG_FILE)).on('finish', resolve);
57+
});
58+
59+
const tmp = tempfile();
60+
61+
changelogStream
62+
.pipe(addStream(readStream))
63+
.pipe(fs.createWriteStream(tmp))
64+
.on('finish', () => {
65+
fs.createReadStream(tmp).pipe(fs.createWriteStream(CHANGELOG_FILE)).on('finish', resolve);
66+
});
67+
}).then(() => {
68+
console.log(`${chalk.green('UPDATED')} ${CHANGELOG_FILE} ${chalk.gray(pkg.version)}`);
69+
});
70+
}

0 commit comments

Comments
 (0)