Skip to content

Commit c693f4e

Browse files
committed
chore: custom changesets plugin
1 parent 3dcc4ef commit c693f4e

File tree

5 files changed

+390
-2
lines changed

5 files changed

+390
-2
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { getInfo, getInfoFromPullRequest } from "@changesets/get-github-info";
2+
import { config } from "dotenv";
3+
4+
config();
5+
6+
/**
7+
* @type {import("@changesets/types").ChangelogFunctions}
8+
*/
9+
const changelogFunctions = {
10+
getDependencyReleaseLine: async (
11+
changesets,
12+
dependenciesUpdated,
13+
options,
14+
) => {
15+
if (!options.repo) {
16+
throw new Error(
17+
"Please provide a repo to this changelog generator like this:\n\"changelog\": [\"@changesets/changelog-github\", { \"repo\": \"org/repo\" }]",
18+
);
19+
}
20+
if (dependenciesUpdated.length === 0) return "";
21+
22+
const changesetLink = `Updated dependencies [${(
23+
await Promise.all(
24+
changesets.map(async (cs) => {
25+
if (cs.commit) {
26+
let { links } = await getInfo({
27+
repo: options.repo,
28+
commit: cs.commit,
29+
});
30+
return links.commit;
31+
}
32+
}),
33+
)
34+
)
35+
.filter((_) => _)
36+
.join(", ")}]:`;
37+
38+
const updatedDepenenciesList = dependenciesUpdated.map(
39+
(dependency) => ` - ${dependency.name}@${dependency.newVersion}`,
40+
);
41+
42+
return [changesetLink, ...updatedDepenenciesList].join("\n");
43+
},
44+
getReleaseLine: async (changeset, type, options) => {
45+
if (!options || !options.repo) {
46+
throw new Error(
47+
"Please provide a repo to this changelog generator like this:\n\"changelog\": [\"@changesets/changelog-github\", { \"repo\": \"org/repo\" }]",
48+
);
49+
}
50+
51+
/** @type {number | undefined} */
52+
let prFromSummary;
53+
/** @type {string | undefined} */
54+
let commitFromSummary;
55+
/** @type {string[]} */
56+
let usersFromSummary = [];
57+
58+
const replacedChangelog = changeset.summary
59+
.replace(/^\s*(?:pr|pull|pull\s+request):\s*#?(\d+)/im, (_, pr) => {
60+
let num = Number(pr);
61+
if (!isNaN(num)) prFromSummary = num;
62+
return "";
63+
})
64+
.replace(/^\s*commit:\s*([^\s]+)/im, (_, commit) => {
65+
commitFromSummary = commit;
66+
return "";
67+
})
68+
.replace(/^\s*(?:author|user):\s*@?([^\s]+)/gim, (_, user) => {
69+
usersFromSummary.push(user);
70+
return "";
71+
})
72+
.trim();
73+
74+
const changelogLines = replacedChangelog
75+
.split("\n")
76+
.map((l) => l.trimRight());
77+
78+
const links = await (async () => {
79+
if (prFromSummary !== undefined) {
80+
let { links } = await getInfoFromPullRequest({
81+
repo: options.repo,
82+
pull: prFromSummary,
83+
});
84+
if (commitFromSummary) {
85+
const shortCommitId = commitFromSummary.slice(0, 7);
86+
links = {
87+
...links,
88+
commit: `[\`${shortCommitId}\`](https://github.com/${options.repo}/commit/${commitFromSummary})`,
89+
};
90+
}
91+
return links;
92+
}
93+
const commitToFetchFrom = commitFromSummary || changeset.commit;
94+
if (commitToFetchFrom) {
95+
let { links } = await getInfo({
96+
repo: options.repo,
97+
commit: commitToFetchFrom,
98+
});
99+
return links;
100+
}
101+
return { commit: null, pull: null, user: null };
102+
})();
103+
104+
const users = usersFromSummary.length
105+
? usersFromSummary
106+
.map(
107+
(userFromSummary) =>
108+
`[@${userFromSummary}](https://github.com/${userFromSummary})`,
109+
)
110+
.join(", ")
111+
: links.user;
112+
113+
const prefix = [
114+
links.pull === null ? "" : ` ${links.pull}`,
115+
links.commit === null ? "" : ` ${links.commit}`,
116+
users === null ? "" : ` Thanks ${users}!`,
117+
].join("");
118+
119+
return `\n\n📝 ${prefix ? `${prefix}` : ""}\n\n${changelogLines.join("\n")}`;
120+
},
121+
};
122+
123+
export default changelogFunctions;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "@spectrum-tools/changesets-changelog-github",
3+
"version": "0.0.0",
4+
"description": "A changelog entry generator for GitHub that links to commits, PRs and users",
5+
"license": "Apache-2.0",
6+
"author": "Adobe",
7+
"homepage": "https://opensource.adobe.com/spectrum-css/",
8+
"repository": {
9+
"type": "git",
10+
"url": "https://github.com/adobe/spectrum-css.git",
11+
"directory": "plugins/changesets-changelog-github"
12+
},
13+
"bugs": {
14+
"url": "https://github.com/adobe/spectrum-css/issues"
15+
},
16+
"type": "module",
17+
"module": "index.js",
18+
"dependencies": {
19+
"@changesets/get-github-info": "^0.6.0",
20+
"@changesets/types": "^6.1.0",
21+
"dotenv": "^16.4.7"
22+
},
23+
"devDependencies": {
24+
"@changesets/parse": "^0.4.1",
25+
"ava": "^6.2.0",
26+
"sinon": "^20.0.0"
27+
},
28+
"keywords": [
29+
"design-system",
30+
"spectrum",
31+
"spectrum-css",
32+
"adobe",
33+
"adobe-spectrum"
34+
]
35+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
3+
"name": "changesets-changelog-github",
4+
"tags": ["tooling", "changesets", "plugin"],
5+
"targets": {
6+
"format": { "defaultConfiguration": "plugins" },
7+
"lint": { "defaultConfiguration": "plugins" },
8+
"test": { "defaultConfiguration": "plugins" }
9+
}
10+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import parse from "@changesets/parse";
2+
import test from "ava";
3+
import sinon from "sinon";
4+
import changelogFunctions from "./index.js";
5+
6+
/** @type {sinon.SinonSandbox} */
7+
let sandbox;
8+
9+
const data = {
10+
commit: "a085003",
11+
user: "Andarist",
12+
pull: 1613,
13+
repo: "emotion-js/emotion",
14+
};
15+
16+
test.beforeEach((t) => {
17+
sandbox = sinon.createSandbox();
18+
const stub = sandbox.stub("@changesets/get-github-info");
19+
stub.getInfo.returns({
20+
pull: data.pull,
21+
user: data.user,
22+
links: {
23+
user: `[@${data.user}](https://github.com/${data.user})`,
24+
pull: `[#${data.pull}](https://github.com/${data.repo}/pull/${data.pull})`,
25+
commit: `[\`${data.commit}\`](https://github.com/${data.repo}/commit/${data.commit})`,
26+
},
27+
});
28+
29+
stub.getInfoFromPullRequest.returns({
30+
commit: data.commit,
31+
user: data.user,
32+
links: {
33+
user: `[@${data.user}](https://github.com/${data.user})`,
34+
pull: `[#${data.pull}](https://github.com/${data.repo}/pull/${data.pull})`,
35+
commit: `[\`${data.commit}\`](https://github.com/${data.repo}/commit/${data.commit})`,
36+
},
37+
});
38+
});
39+
40+
test.afterEach.always(() => {
41+
sandbox.restore();
42+
});
43+
44+
/**
45+
*
46+
* @param {string} content
47+
* @param {string|undefined} commit
48+
* @returns
49+
*/
50+
const getChangeset = (content, commit) => {
51+
return [
52+
{
53+
...parse(
54+
`---
55+
pkg: "minor"
56+
---
57+
58+
something
59+
${content}
60+
`
61+
),
62+
id: "some-id",
63+
commit,
64+
},
65+
"minor",
66+
{ repo: data.repo },
67+
];
68+
};
69+
70+
[data.commit, "wrongcommit", undefined].forEach((commitFromChangeset) => {
71+
["pr", "pull request", "pull"].forEach((keyword) => {
72+
test(`with commit from changeset of ${commitFromChangeset} override pr with ${keyword} keyword with #`, async (t) => {
73+
t.is(
74+
await changelogFunctions.getReleaseLine(
75+
...getChangeset(
76+
`${keyword}: #${data.pull}`,
77+
commitFromChangeset
78+
)
79+
),
80+
"\n\n- [#1613](https://github.com/emotion-js/emotion/pull/1613) [`a085003`](https://github.com/emotion-js/emotion/commit/a085003) Thanks [@Andarist](https://github.com/Andarist)! - something\n"
81+
);
82+
});
83+
84+
test(`with commit from changeset of ${commitFromChangeset} override pr with pr ${keyword} without #`, async (t) => {
85+
t.is(
86+
await changelogFunctions.getReleaseLine(
87+
...getChangeset(
88+
`pr: ${data.pull}`,
89+
commitFromChangeset
90+
)
91+
),
92+
"\n\n- [#1613](https://github.com/emotion-js/emotion/pull/1613) [`a085003`](https://github.com/emotion-js/emotion/commit/a085003) Thanks [@Andarist](https://github.com/Andarist)! - something\n"
93+
);
94+
});
95+
});
96+
97+
test(`override commit ${commitFromChangeset} with commit keyword`, async (t) => {
98+
t.is(
99+
await changelogFunctions.getReleaseLine(
100+
...getChangeset(`commit: ${data.commit}`, commitFromChangeset)
101+
),
102+
"\n\n- [#1613](https://github.com/emotion-js/emotion/pull/1613) [`a085003`](https://github.com/emotion-js/emotion/commit/a085003) Thanks [@Andarist](https://github.com/Andarist)! - something\n"
103+
);
104+
});
105+
});
106+
107+
["author", "user"].forEach((keyword) => {
108+
test(`override author with ${keyword} keyword with @`, async (t) => {
109+
t.is(
110+
await changelogFunctions.getReleaseLine(
111+
...getChangeset(
112+
`${keyword}: @other`,
113+
data.commit
114+
)
115+
),
116+
"\n\n- [#1613](https://github.com/emotion-js/emotion/pull/1613) [`a085003`](https://github.com/emotion-js/emotion/commit/a085003) Thanks [@other](https://github.com/other)!\n\nsomething\n"
117+
);
118+
});
119+
120+
test(`override author with ${keyword} keyword without @`, async (t) => {
121+
t.is(
122+
await changelogFunctions.getReleaseLine(
123+
...getChangeset(
124+
`${keyword}: other`,
125+
data.commit
126+
)
127+
),
128+
"\n\n- [#1613](https://github.com/emotion-js/emotion/pull/1613) [`a085003`](https://github.com/emotion-js/emotion/commit/a085003) Thanks [@other](https://github.com/other)!\n\nsomething\n"
129+
);
130+
});
131+
});
132+
133+
test("with multiple authors", async (t) => {
134+
t.is(
135+
await changelogFunctions.getReleaseLine(
136+
...getChangeset(
137+
["author: @Andarist", "author: @mitchellhamilton"].join("\n"),
138+
data.commit
139+
)
140+
),
141+
`
142+
- [#1613](https://github.com/emotion-js/emotion/pull/1613) [\`a085003\`](https://github.com/emotion-js/emotion/commit/a085003) Thanks [@Andarist](https://github.com/Andarist), [@mitchellhamilton](https://github.com/mitchellhamilton)!\n\nsomething`);
143+
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy