Skip to content

Commit

Permalink
Merge pull request #1 from s0/github-api-tag-push
Browse files Browse the repository at this point in the history
Start using the GitHub API to push changes (both tags and commits) to GitHub
  • Loading branch information
s0 authored Aug 25, 2024
2 parents 89b41e6 + c12277b commit a71f3a9
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 85 deletions.
10 changes: 10 additions & 0 deletions .changeset/green-dogs-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@changesets/action": major
---

Start using GitHub API to push tags and commits to repos

Rather than use local git commands to push changes to GitHub,
this action now uses the GitHub API directly,
which means that all tags and commits will be attributed to the user whose
GITHUB_TOKEN is used, and signed.
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@
"main": "dist/index.js",
"license": "MIT",
"devDependencies": {
"@changesets/changelog-github": "^0.4.2",
"@changesets/cli": "^2.20.0",
"@changesets/write": "^0.1.6",
"@vercel/ncc": "^0.36.1",
"fixturez": "^1.1.0",
"prettier": "^2.0.5",
"typescript": "^5.0.4",
"@babel/core": "^7.13.10",
"@babel/preset-env": "^7.13.10",
"@babel/preset-typescript": "^7.13.0",
"@changesets/changelog-github": "^0.4.2",
"@changesets/cli": "^2.20.0",
"@changesets/write": "^0.1.6",
"@types/fs-extra": "^8.0.0",
"@types/jest": "^29.5.1",
"@types/node": "^20.11.17",
"@types/semver": "^7.5.0",
"@vercel/ncc": "^0.36.1",
"babel-jest": "^29.5.0",
"fixturez": "^1.1.0",
"husky": "^3.0.3",
"jest": "^29.5.0"
"jest": "^29.5.0",
"prettier": "^2.0.5",
"typescript": "^5.0.4"
},
"scripts": {
"build": "ncc build src/index.ts -o dist --transpile-only --minify",
Expand All @@ -41,6 +41,7 @@
"@changesets/read": "^0.5.3",
"@manypkg/get-packages": "^1.1.3",
"@octokit/plugin-throttling": "^5.2.1",
"@s0/ghcommit": "^1.1.0",
"fs-extra": "^8.1.0",
"mdast-util-to-string": "^1.0.6",
"remark-parse": "^7.0.1",
Expand Down
51 changes: 1 addition & 50 deletions src/gitUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,53 +11,4 @@ export const setupUser = async () => {
"user.email",
`"github-actions[bot]@users.noreply.github.com"`,
]);
};

export const pullBranch = async (branch: string) => {
await exec("git", ["pull", "origin", branch]);
};

export const push = async (
branch: string,
{ force }: { force?: boolean } = {}
) => {
await exec(
"git",
["push", "origin", `HEAD:${branch}`, force && "--force"].filter<string>(
Boolean as any
)
);
};

export const pushTags = async () => {
await exec("git", ["push", "origin", "--tags"]);
};

export const switchToMaybeExistingBranch = async (branch: string) => {
let { stderr } = await getExecOutput("git", ["checkout", branch], {
ignoreReturnCode: true,
});
let isCreatingBranch = !stderr
.toString()
.includes(`Switched to a new branch '${branch}'`);
if (isCreatingBranch) {
await exec("git", ["checkout", "-b", branch]);
}
};

export const reset = async (
pathSpec: string,
mode: "hard" | "soft" | "mixed" = "hard"
) => {
await exec("git", ["reset", `--${mode}`, pathSpec]);
};

export const commitAll = async (message: string) => {
await exec("git", ["add", "."]);
await exec("git", ["commit", "-m", message]);
};

export const checkIfClean = async (): Promise<boolean> => {
const { stdout } = await getExecOutput("git", ["status", "--porcelain"]);
return !stdout.length;
};
};
1 change: 1 addition & 0 deletions src/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jest.mock("@actions/github/lib/utils", () => ({
getOctokitOptions: jest.fn(),
}));
jest.mock("./gitUtils");
jest.mock("@s0/ghcommit/git");

let mockedGithubMethods = {
search: {
Expand Down
67 changes: 42 additions & 25 deletions src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import * as gitUtils from "./gitUtils";
import readChangesetState from "./readChangesetState";
import resolveFrom from "resolve-from";
import { throttling } from "@octokit/plugin-throttling";
import { commitChangesFromRepo } from "@s0/ghcommit/git";

// GitHub Issues/PRs messages have a max size limit on the
// message body payload.
Expand Down Expand Up @@ -130,8 +131,6 @@ export async function runPublish({
{ cwd }
);

await gitUtils.pushTags();

let { packages, tool } = await getPackages(cwd);
let releasedPackages: Package[] = [];

Expand All @@ -157,12 +156,19 @@ export async function runPublish({

if (createGithubReleases) {
await Promise.all(
releasedPackages.map((pkg) =>
createRelease(octokit, {
pkg,
tagName: `${pkg.packageJson.name}@${pkg.packageJson.version}`,
})
)
releasedPackages.map(async (pkg) => {
const tagName = `${pkg.packageJson.name}@${pkg.packageJson.version}`;
// Tag will only be created locally,
// Create it using the GitHub API so it's signed.
await octokit.rest.git.createRef({
...github.context.repo,
ref: `refs/tags/${tagName}`,
sha: github.context.sha,
});
if (createGithubReleases) {
await createRelease(octokit, { pkg, tagName });
}
})
);
}
} else {
Expand All @@ -180,11 +186,16 @@ export async function runPublish({

if (match) {
releasedPackages.push(pkg);
const tagName = `v${pkg.packageJson.version}`;
// Tag will only be created locally,
// Create it using the GitHub API so it's signed.
await octokit.rest.git.createRef({
...github.context.repo,
ref: `refs/tags/${tagName}`,
sha: github.context.sha,
});
if (createGithubReleases) {
await createRelease(octokit, {
pkg,
tagName: `v${pkg.packageJson.version}`,
});
await createRelease(octokit, { pkg, tagName });
}
break;
}
Expand Down Expand Up @@ -324,9 +335,6 @@ export async function runVersion({

let { preState } = await readChangesetState(cwd);

await gitUtils.switchToMaybeExistingBranch(versionBranch);
await gitUtils.reset(github.context.sha);

let versionsByDirectory = await getVersionsByDirectory(cwd);

if (script) {
Expand Down Expand Up @@ -365,16 +373,25 @@ export async function runVersion({
);

const finalPrTitle = `${prTitle}${!!preState ? ` (${preState.tag})` : ""}`;

// project with `commit: true` setting could have already committed files
if (!(await gitUtils.checkIfClean())) {
const finalCommitMessage = `${commitMessage}${
!!preState ? ` (${preState.tag})` : ""
}`;
await gitUtils.commitAll(finalCommitMessage);
}

await gitUtils.push(versionBranch, { force: true });
const finalCommitMessage = `${commitMessage}${
!!preState ? ` (${preState.tag})` : ""
}`;

await commitChangesFromRepo({
octokit,
owner: github.context.repo.owner,
repository: github.context.repo.repo,
branch: versionBranch,
// TODO: switch this to use direct string input when supported
message: {
headline: finalCommitMessage.split("\n", 2)[0].trim(),
body: finalCommitMessage.split("\n", 2)[1]?.trim(),
},
base: {
commit: github.context.sha,
},
force: true,
});

let searchResult = await searchResultPromise;
core.info(JSON.stringify(searchResult.data, null, 2));
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */

/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"moduleResolution": "nodenext", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
Expand Down
Loading

0 comments on commit a71f3a9

Please sign in to comment.