mirror of
https://github.com/changesets/action
synced 2026-10-26 16:39:56 +08:00
Merge branch 'main' into add-draft-mode-support
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`version creates simple PR 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
[
|
||||
{
|
||||
"base": "some-branch",
|
||||
"body": "This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or [setup this action to publish automatically](https://github.com/changesets/action#with-publishing). If you're not ready to do a release yet, that's fine, whenever you add more changesets to some-branch, this PR will be updated.
|
||||
|
||||
@@ -34,8 +34,8 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`version does not include any release information if a message with simplified release info exceeds size limit 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
[
|
||||
{
|
||||
"base": "some-branch",
|
||||
"body": "This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or [setup this action to publish automatically](https://github.com/changesets/action#with-publishing). If you're not ready to do a release yet, that's fine, whenever you add more changesets to some-branch, this PR will be updated.
|
||||
|
||||
@@ -52,8 +52,8 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`version does not include changelog entries if full message exceeds size limit 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
[
|
||||
{
|
||||
"base": "some-branch",
|
||||
"body": "This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or [setup this action to publish automatically](https://github.com/changesets/action#with-publishing). If you're not ready to do a release yet, that's fine, whenever you add more changesets to some-branch, this PR will be updated.
|
||||
|
||||
@@ -74,8 +74,8 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`version doesn't include ignored package that got a dependency update in the PR body 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
[
|
||||
{
|
||||
"base": "some-branch",
|
||||
"body": "This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or [setup this action to publish automatically](https://github.com/changesets/action#with-publishing). If you're not ready to do a release yet, that's fine, whenever you add more changesets to some-branch, this PR will be updated.
|
||||
|
||||
@@ -96,8 +96,8 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`version only includes bumped packages in the PR body 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
[
|
||||
{
|
||||
"base": "some-branch",
|
||||
"body": "This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and publish to npm yourself or [setup this action to publish automatically](https://github.com/changesets/action#with-publishing). If you're not ready to do a release yet, that's fine, whenever you add more changesets to some-branch, this PR will be updated.
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`it sorts the things right 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
[
|
||||
{
|
||||
"highestLevel": 3,
|
||||
"name": "c",
|
||||
"private": false,
|
||||
},
|
||||
Object {
|
||||
{
|
||||
"highestLevel": 1,
|
||||
"name": "b",
|
||||
"private": false,
|
||||
},
|
||||
Object {
|
||||
{
|
||||
"highestLevel": 3,
|
||||
"name": "a",
|
||||
"private": true,
|
||||
|
||||
+12
-11
@@ -16,18 +16,18 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
|
||||
|
||||
const inputCwd = core.getInput("cwd");
|
||||
if (inputCwd) {
|
||||
console.log("changing directory to the one given as the input");
|
||||
core.info("changing directory to the one given as the input");
|
||||
process.chdir(inputCwd);
|
||||
}
|
||||
|
||||
let setupGitUser = core.getBooleanInput("setupGitUser");
|
||||
|
||||
if (setupGitUser) {
|
||||
console.log("setting git user");
|
||||
core.info("setting git user");
|
||||
await gitUtils.setupUser();
|
||||
}
|
||||
|
||||
console.log("setting GitHub credentials");
|
||||
core.info("setting GitHub credentials");
|
||||
await fs.writeFile(
|
||||
`${process.env.HOME}/.netrc`,
|
||||
`machine github.com\nlogin github-actions[bot]\npassword ${githubToken}`
|
||||
@@ -48,27 +48,27 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
|
||||
|
||||
switch (true) {
|
||||
case !hasChangesets && !hasPublishScript:
|
||||
console.log("No changesets found");
|
||||
core.info("No changesets found");
|
||||
return;
|
||||
case !hasChangesets && hasPublishScript: {
|
||||
console.log(
|
||||
core.info(
|
||||
"No changesets found, attempting to publish any unpublished packages to npm"
|
||||
);
|
||||
|
||||
let userNpmrcPath = `${process.env.HOME}/.npmrc`;
|
||||
if (fs.existsSync(userNpmrcPath)) {
|
||||
console.log("Found existing user .npmrc file");
|
||||
core.info("Found existing user .npmrc file");
|
||||
const userNpmrcContent = await fs.readFile(userNpmrcPath, "utf8");
|
||||
const authLine = userNpmrcContent.split("\n").find((line) => {
|
||||
// check based on https://github.com/npm/cli/blob/8f8f71e4dd5ee66b3b17888faad5a7bf6c657eed/test/lib/adduser.js#L103-L105
|
||||
return /^\s*\/\/registry\.npmjs\.org\/:[_-]authToken=/i.test(line);
|
||||
});
|
||||
if (authLine) {
|
||||
console.log(
|
||||
core.info(
|
||||
"Found existing auth token for the npm registry in the user .npmrc file"
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
core.info(
|
||||
"Didn't find existing auth token for the npm registry in the user .npmrc file, creating one"
|
||||
);
|
||||
fs.appendFileSync(
|
||||
@@ -77,7 +77,7 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.log("No user .npmrc file found, creating one");
|
||||
core.info("No user .npmrc file found, creating one");
|
||||
fs.writeFileSync(
|
||||
userNpmrcPath,
|
||||
`//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}\n`
|
||||
@@ -100,7 +100,7 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
|
||||
return;
|
||||
}
|
||||
case hasChangesets && !hasNonEmptyChangesets:
|
||||
console.log("All changesets are empty; not creating PR");
|
||||
core.info("All changesets are empty; not creating PR");
|
||||
return;
|
||||
case hasChangesets:
|
||||
const { pullRequestNumber } = await runVersion({
|
||||
@@ -110,6 +110,7 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
|
||||
commitMessage: getOptionalInput("commit"),
|
||||
hasPublishScript,
|
||||
createPrAsDraft: core.getBooleanInput("createPrAsDraft"),
|
||||
branch: getOptionalInput("branch"),
|
||||
});
|
||||
|
||||
core.setOutput("pullRequestNumber", String(pullRequestNumber));
|
||||
@@ -117,6 +118,6 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined;
|
||||
return;
|
||||
}
|
||||
})().catch((err) => {
|
||||
console.error(err);
|
||||
core.error(err);
|
||||
core.setFailed(err.message);
|
||||
});
|
||||
|
||||
@@ -11,17 +11,19 @@ export default async function readChangesetState(
|
||||
cwd: string = process.cwd()
|
||||
): Promise<ChangesetState> {
|
||||
let preState = await readPreState(cwd);
|
||||
let isInPreMode = preState !== undefined && preState.mode === "pre";
|
||||
|
||||
let changesets = await readChangesets(cwd);
|
||||
|
||||
if (isInPreMode) {
|
||||
if (preState !== undefined && preState.mode === "pre") {
|
||||
let changesetsToFilter = new Set(preState.changesets);
|
||||
changesets = changesets.filter((x) => !changesetsToFilter.has(x.id));
|
||||
|
||||
return {
|
||||
preState,
|
||||
changesets: changesets.filter((x) => !changesetsToFilter.has(x.id)),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
preState: isInPreMode ? preState : undefined,
|
||||
preState: undefined,
|
||||
changesets,
|
||||
};
|
||||
}
|
||||
|
||||
+14
-4
@@ -1,5 +1,6 @@
|
||||
import fixturez from "fixturez";
|
||||
import * as github from "@actions/github";
|
||||
import * as githubUtils from "@actions/github/lib/utils";
|
||||
import fs from "fs-extra";
|
||||
import path from "path";
|
||||
import writeChangeset from "@changesets/write";
|
||||
@@ -15,7 +16,19 @@ jest.mock("@actions/github", () => ({
|
||||
ref: "refs/heads/some-branch",
|
||||
sha: "xeac7",
|
||||
},
|
||||
getOctokit: jest.fn(),
|
||||
}));
|
||||
jest.mock("@actions/github/lib/utils", () => ({
|
||||
GitHub: {
|
||||
plugin: () => {
|
||||
// function necessary to be used as constructor
|
||||
return function() {
|
||||
return {
|
||||
rest: mockedGithubMethods,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
getOctokitOptions: jest.fn(),
|
||||
}));
|
||||
jest.mock("./gitUtils");
|
||||
|
||||
@@ -30,9 +43,6 @@ let mockedGithubMethods = {
|
||||
createRelease: jest.fn(),
|
||||
},
|
||||
};
|
||||
(github.getOctokit as any).mockImplementation(() => ({
|
||||
rest: mockedGithubMethods,
|
||||
}));
|
||||
|
||||
let f = fixturez(__dirname);
|
||||
|
||||
|
||||
+61
-9
@@ -1,5 +1,7 @@
|
||||
import { exec, getExecOutput } from "@actions/exec";
|
||||
import { GitHub, getOctokitOptions } from "@actions/github/lib/utils";
|
||||
import * as github from "@actions/github";
|
||||
import * as core from "@actions/core";
|
||||
import fs from "fs-extra";
|
||||
import { getPackages, Package } from "@manypkg/get-packages";
|
||||
import path from "path";
|
||||
@@ -14,6 +16,7 @@ import {
|
||||
import * as gitUtils from "./gitUtils";
|
||||
import readChangesetState from "./readChangesetState";
|
||||
import resolveFrom from "resolve-from";
|
||||
import { throttling } from "@octokit/plugin-throttling";
|
||||
|
||||
// GitHub Issues/PRs messages have a max size limit on the
|
||||
// message body payload.
|
||||
@@ -21,8 +24,42 @@ import resolveFrom from "resolve-from";
|
||||
// To avoid that, we ensure to cap the message to 60k chars.
|
||||
const MAX_CHARACTERS_PER_MESSAGE = 60000;
|
||||
|
||||
const setupOctokit = (githubToken: string) => {
|
||||
return new (GitHub.plugin(throttling))(
|
||||
getOctokitOptions(githubToken, {
|
||||
throttle: {
|
||||
onRateLimit: (retryAfter, options: any, octokit, retryCount) => {
|
||||
core.warning(
|
||||
`Request quota exhausted for request ${options.method} ${options.url}`
|
||||
);
|
||||
|
||||
if (retryCount <= 2) {
|
||||
core.info(`Retrying after ${retryAfter} seconds!`);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onSecondaryRateLimit: (
|
||||
retryAfter,
|
||||
options: any,
|
||||
octokit,
|
||||
retryCount
|
||||
) => {
|
||||
core.warning(
|
||||
`SecondaryRateLimit detected for request ${options.method} ${options.url}`
|
||||
);
|
||||
|
||||
if (retryCount <= 2) {
|
||||
core.info(`Retrying after ${retryAfter} seconds!`);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const createRelease = async (
|
||||
octokit: ReturnType<typeof github.getOctokit>,
|
||||
octokit: ReturnType<typeof setupOctokit>,
|
||||
{ pkg, tagName }: { pkg: Package; tagName: string }
|
||||
) => {
|
||||
try {
|
||||
@@ -48,7 +85,12 @@ const createRelease = async (
|
||||
});
|
||||
} catch (err) {
|
||||
// if we can't find a changelog, the user has probably disabled changelogs
|
||||
if (err.code !== "ENOENT") {
|
||||
if (
|
||||
err &&
|
||||
typeof err === "object" &&
|
||||
"code" in err &&
|
||||
err.code !== "ENOENT"
|
||||
) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +120,8 @@ export async function runPublish({
|
||||
createGithubReleases,
|
||||
cwd = process.cwd(),
|
||||
}: PublishOptions): Promise<PublishResult> {
|
||||
let octokit = github.getOctokit(githubToken);
|
||||
const octokit = setupOctokit(githubToken);
|
||||
|
||||
let [publishCommand, ...publishArgs] = script.split(/\s+/);
|
||||
|
||||
let changesetPublishOutput = await getExecOutput(
|
||||
@@ -165,7 +208,12 @@ const requireChangesetsCliPkgJson = (cwd: string) => {
|
||||
try {
|
||||
return require(resolveFrom(cwd, "@changesets/cli/package.json"));
|
||||
} catch (err) {
|
||||
if (err && err.code === "MODULE_NOT_FOUND") {
|
||||
if (
|
||||
err &&
|
||||
typeof err === "object" &&
|
||||
"code" in err &&
|
||||
err.code === "MODULE_NOT_FOUND"
|
||||
) {
|
||||
throw new Error(
|
||||
`Have you forgotten to install \`@changesets/cli\` in "${cwd}"?`
|
||||
);
|
||||
@@ -252,6 +300,7 @@ type VersionOptions = {
|
||||
hasPublishScript?: boolean;
|
||||
prBodyMaxCharacters?: number;
|
||||
createPrAsDraft?: boolean;
|
||||
branch?: string;
|
||||
};
|
||||
|
||||
type RunVersionResult = {
|
||||
@@ -267,11 +316,14 @@ export async function runVersion({
|
||||
hasPublishScript = false,
|
||||
prBodyMaxCharacters = MAX_CHARACTERS_PER_MESSAGE,
|
||||
createPrAsDraft = false,
|
||||
branch,
|
||||
}: VersionOptions): Promise<RunVersionResult> {
|
||||
const octokit = setupOctokit(githubToken);
|
||||
|
||||
let repo = `${github.context.repo.owner}/${github.context.repo.repo}`;
|
||||
let branch = github.context.ref.replace("refs/heads/", "");
|
||||
branch = branch ?? github.context.ref.replace("refs/heads/", "");
|
||||
let versionBranch = `changeset-release/${branch}`;
|
||||
let octokit = github.getOctokit(githubToken);
|
||||
|
||||
let { preState } = await readChangesetState(cwd);
|
||||
|
||||
await gitUtils.switchToMaybeExistingBranch(versionBranch);
|
||||
@@ -327,7 +379,7 @@ export async function runVersion({
|
||||
await gitUtils.push(versionBranch, { force: true });
|
||||
|
||||
let searchResult = await searchResultPromise;
|
||||
console.log(JSON.stringify(searchResult.data, null, 2));
|
||||
core.info(JSON.stringify(searchResult.data, null, 2));
|
||||
|
||||
const changedPackagesInfo = (await changedPackagesInfoPromises)
|
||||
.filter((x) => x)
|
||||
@@ -342,7 +394,7 @@ export async function runVersion({
|
||||
});
|
||||
|
||||
if (searchResult.data.items.length === 0) {
|
||||
console.log("creating pull request");
|
||||
core.info("creating pull request");
|
||||
const { data: newPullRequest } = await octokit.rest.pulls.create({
|
||||
base: branch,
|
||||
head: versionBranch,
|
||||
@@ -358,7 +410,7 @@ export async function runVersion({
|
||||
} else {
|
||||
const [pullRequest] = searchResult.data.items;
|
||||
|
||||
console.log(`updating found pull request #${pullRequest.number}`);
|
||||
core.info(`updating found pull request #${pullRequest.number}`);
|
||||
await octokit.rest.pulls.update({
|
||||
pull_number: pullRequest.number,
|
||||
title: finalPrTitle,
|
||||
|
||||
@@ -3,7 +3,6 @@ import remarkParse from "remark-parse";
|
||||
import remarkStringify from "remark-stringify";
|
||||
// @ts-ignore
|
||||
import mdastToString from "mdast-util-to-string";
|
||||
import { exec } from "@actions/exec";
|
||||
import { getPackages, Package } from "@manypkg/get-packages";
|
||||
|
||||
export const BumpLevels = {
|
||||
|
||||
Reference in New Issue
Block a user