diff --git a/.changeset/humble-weeks-watch.md b/.changeset/humble-weeks-watch.md new file mode 100644 index 0000000..9eeec5e --- /dev/null +++ b/.changeset/humble-weeks-watch.md @@ -0,0 +1,8 @@ +--- +"@changesets/ghcommit": major +--- + +Removed the `commitFilesFromBuffers` and `commitFilesFromDirectory` APIs. These APIs were simple wrappers over the core `commitChangesFromBase64` API, which should be used instead. Read the file and pass the base64-encoded content to `commitChangesFromBase64` `fileChanges` directly. For example: + +- `Buffer.from("hello world").toString("base64")` +- `await fs.readFile("path/to/file", "base64")` diff --git a/.changeset/slick-bottles-try.md b/.changeset/slick-bottles-try.md new file mode 100644 index 0000000..5a978b6 --- /dev/null +++ b/.changeset/slick-bottles-try.md @@ -0,0 +1,5 @@ +--- +"@changesets/ghcommit": major +--- + +Removed all subpath exports. All APIs should be imported from root, e.g. `import { commitChangesFromRepo } from "@changesets/ghcommit"`. diff --git a/README.md b/README.md index b7c405e..1ec4bf8 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ pnpm install @changesets/ghcommit ### Usage in github actions -All functions in this library that interact with the GitHub API require an octokit client that can execute GraphQL. If you are writing code that is designed to be run from within a GitHub Action, this can be done using the `@actions.github` library: +All functions in this library that interact with the GitHub API require an octokit client that can execute GraphQL. If you are writing code that is designed to be run from within a GitHub Action, this can be done using the `@actions/github` library: ```ts import { getOctokit } from "@actions/github"; @@ -48,10 +48,6 @@ import { getOctokit } from "@actions/github"; const octokit = getOctokit(process.env.GITHUB_TOKEN); ``` -### Importing specific modules - -To allow for you to produce smaller bundle sizes, the functionality exposed in this package is grouped into specific modules that only import the packages required for their use. We recommend that you import from the specific modules rather than the root of the package. - ## API All the functions below accept a single object as its argument, and share the following base arguments: @@ -77,8 +73,66 @@ All the functions below accept a single object as its argument, and share the fo } ``` +### `commitFilesFromBase64` + +> Works in Node.js and browsers + +This function will add or delete specific files from a repository's branch based on the given `fileChanges` argument. + +In addition to `CommitFilesBasedArgs`, this function has the following arguments: + +```ts +{ + /** + * The current branch, tag or commit that the new branch should be based on. + */ + base: GitBase; + /** + * The file paths, relative to git root, to add or delete from the branch on GitHub. + */ + fileChanges: { + /** + * File paths, relative to git root, to add to the repo. Content is a base64-encoded string. + */ + additions?: { path: string; content: string }[]; + /** + * File paths, relative to git root, to remove from the repo. + */ + deletions?: { path: string }[]; + }; +} +``` + +Example: + +```ts +import fs from "node:fs/promises"; +import { context, getOctokit } from "@actions/github"; +import { commitFilesFromBase64 } from "@changesets/ghcommit"; + +const octokit = getOctokit(process.env.GITHUB_TOKEN); + +// Commit the changes to README.md based on the main branch +await commitFilesFromBase64({ + octokit, + ...context.repo, + branch: "new-branch-to-create", + message: "[chore] do something", + base: { + branch: "main", + }, + fileChanges: { + additions: [ + { path: "README.md", content: await fs.readFile("README.md", "base64") }, + ], + }, +}); +``` + ### `commitChangesFromRepo` +> Works in Node.js only + This function will take an existing repository on your filesystem (defaulting to the current working directory). This function is good to use if you're usually working within the context of a git repository, such as after running `@actions/checkout` in github actions. In addition to `CommitFilesBasedArgs`, this function has the following arguments: @@ -122,7 +176,7 @@ Example: ```ts import { context, getOctokit } from "@actions/github"; -import { commitChangesFromRepo } from "@changesets/ghcommit/git"; +import { commitChangesFromRepo } from "@changesets/ghcommit"; const octokit = getOctokit(process.env.GITHUB_TOKEN); @@ -166,130 +220,6 @@ await commitChangesFromRepo({ }); ``` -### `commitFilesFromDirectory` - -This function will add or delete specific files from a repository's branch based on files found on the local filesystem. This is good to use when there are specific files that need to be updated on a branch, or if many changes may have been made locally, but only some files need to be pushed. - -In addition to `CommitFilesBasedArgs`, this function has the following arguments: - -```ts -{ - /** - * The current branch, tag or commit that the new branch should be based on. - */ - base: GitBase; - /** - * The directory to consider the root of the repository when calculating - * file paths - */ - cwd: string; - /** - * The file paths, relative to {@link workingDirectory}, - * to add or delete from the branch on GitHub. - */ - fileChanges: { - /** File paths, relative to {@link workingDirectory}, to remove from the repo. */ - additions?: string[]; - /** File paths, relative to the repository root, to remove from the repo. */ - deletions?: string[]; - }; -} -``` - -Example: - -```ts -import { context, getOctokit } from "@actions/github"; -import { commitFilesFromDirectory } from "@changesets/ghcommit/fs"; - -const octokit = getOctokit(process.env.GITHUB_TOKEN); - -// Commit the changes to package.json and package-lock.json -// based on the main branch -await commitFilesFromDirectory({ - octokit, - ...context.repo, - branch: "new-branch-to-create", - message: "[chore] do something", - base: { - branch: "main", - }, - cwd: "foo/bar", - fileChanges: { - additions: ["package-lock.json", "package.json"], - }, -}); - -// Push just the index.html file to a new branch called docs, based off the tag v1.0.0 -await commitFilesFromDirectory({ - octokit, - ...context.repo, - branch: "docs", - message: "[chore] do something", - force: true, // Overwrite any existing branch - base: { - tag: "v1.0.0", - }, - cwd: "some-dir", - fileChanges: { - additions: ["index.html"], - }, -}); -``` - -### `commitFilesFromBuffers` - -This function will add or delete specific files from a repository's branch based on Node.js `Buffers` that can be any binary data in memory. This is useful for when you want to make changes to a repository / branch without cloning a repo or interacting with a filesystem. - -In addition to `CommitFilesBasedArgs`, this function has the following arguments: - -```ts -{ - /** - * The current branch, tag or commit that the new branch should be based on. - */ - base: GitBase; - /** - * The file changes, relative to the repository root, to make to the specified branch. - */ - fileChanges: { - additions?: Array<{ - path: string; - contents: Buffer; - }>; - deletions?: string[]; - }; -} -``` - -Example: - -```ts -import { context, getOctokit } from "@actions/github"; -import { commitFilesFromBuffers } from "@changesets/ghcommit/node"; - -const octokit = getOctokit(process.env.GITHUB_TOKEN); - -// Add a file called hello-world -await commitFilesFromBuffers({ - octokit, - ...context.repo, - branch: "new-branch-to-create", - message: "[chore] do something", - base: { - branch: "main", - }, - fileChanges: { - additions: [ - { - path: "hello/world.txt", - contents: Buffer.alloc(1024, "Hello, world!"), - }, - ], - }, -}); -``` - ## Known Limitations Due to using the GitHub API to make changes to repository contents, diff --git a/package.json b/package.json index b74096d..1453c06 100644 --- a/package.json +++ b/package.json @@ -23,11 +23,13 @@ "type": "module", "sideEffects": false, "exports": { - ".": "./dist/index.mjs", - "./core": "./dist/core.mjs", - "./fs": "./dist/fs.mjs", - "./git": "./dist/git.mjs", - "./node": "./dist/node.mjs", + ".": { + "types": "./dist/index-node.d.mts", + "workerd": "./dist/index-node.mjs", + "edge-light": "./dist/index-node.mjs", + "browser": "./dist/index-browser.mjs", + "default": "./dist/index-node.mjs" + }, "./package.json": "./package.json" }, "publishConfig": { diff --git a/src/fs.ts b/src/fs.ts deleted file mode 100644 index 599215d..0000000 --- a/src/fs.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { promises as fs } from "fs"; -import * as path from "path"; -import { commitFilesFromBase64 } from "./core.ts"; -import type { - CommitFilesFromBase64Args, - CommitFilesFromDirectoryArgs, - CommitFilesResult, -} from "./interface.ts"; - -export async function commitFilesFromDirectory({ - cwd, - fileChanges, - ...otherArgs -}: CommitFilesFromDirectoryArgs): Promise { - return await commitFilesFromBase64({ - ...otherArgs, - fileChanges: await normalizeFileChanges(fileChanges, cwd), - }); -} - -// Exported for testing only -export async function normalizeFileChanges( - fileChanges: CommitFilesFromDirectoryArgs["fileChanges"], - cwd: string, -): Promise { - return { - additions: fileChanges.additions - ? await Promise.all( - fileChanges.additions.map(async (a) => ({ - path: a, - contents: await fs.readFile(path.join(cwd, a), "base64"), - })), - ) - : undefined, - deletions: fileChanges.deletions?.map((d) => ({ path: d })), - }; -} diff --git a/src/index-browser.ts b/src/index-browser.ts new file mode 100644 index 0000000..a505688 --- /dev/null +++ b/src/index-browser.ts @@ -0,0 +1,5 @@ +export { commitFilesFromBase64 } from "./core.ts"; + +export function commitChangesFromRepo() { + throw new Error("commitChangesFromRepo is not supported in the browser"); +} diff --git a/src/index.ts b/src/index-node.ts similarity index 66% rename from src/index.ts rename to src/index-node.ts index 2f786a7..1b06cb8 100644 --- a/src/index.ts +++ b/src/index-node.ts @@ -1,3 +1,2 @@ export { commitFilesFromBase64 } from "./core.ts"; export { commitChangesFromRepo } from "./git.ts"; -export { commitFilesFromDirectory } from "./fs.ts"; diff --git a/src/interface.ts b/src/interface.ts index 0bbafe3..19f1d64 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -48,37 +48,6 @@ export interface CommitFilesFromBase64Args extends CommitFilesSharedArgsWithBase fileChanges: FileChanges; } -export interface CommitFilesFromBuffersArgs extends CommitFilesSharedArgsWithBase { - /** - * The file changes, relative to the repository root, to make to the specified branch. - */ - fileChanges: { - additions?: Array<{ - path: string; - contents: Buffer; - }>; - deletions?: string[]; - }; -} - -export interface CommitFilesFromDirectoryArgs extends CommitFilesSharedArgsWithBase { - /** - * The directory to consider the root of the repository when calculating - * file paths - */ - cwd: string; - /** - * The file paths, relative to {@link cwd}, - * to add or delete from the branch on GitHub. - */ - fileChanges: { - /** File paths, relative to {@link cwd}, to remove from the repo. */ - additions?: string[]; - /** File paths, relative to the repository root, to remove from the repo. */ - deletions?: string[]; - }; -} - export interface CommitChangesFromRepoArgs extends CommitFilesBasedArgs { /** * The directory used to find the repository root, diff --git a/src/node.ts b/src/node.ts deleted file mode 100644 index 1103a76..0000000 --- a/src/node.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { commitFilesFromBase64 } from "./core.js"; -import type { - CommitFilesFromBase64Args, - CommitFilesFromBuffersArgs, - CommitFilesResult, -} from "./interface.ts"; - -export async function commitFilesFromBuffers({ - fileChanges, - ...otherArgs -}: CommitFilesFromBuffersArgs): Promise { - return await commitFilesFromBase64({ - ...otherArgs, - fileChanges: normalizeFileChanges(fileChanges), - }); -} - -// Exported for testing only -export function normalizeFileChanges( - fileChanges: CommitFilesFromBuffersArgs["fileChanges"], -): CommitFilesFromBase64Args["fileChanges"] { - return { - additions: fileChanges.additions?.map((a) => ({ - path: a.path, - contents: a.contents.toString("base64"), - })), - deletions: fileChanges.deletions?.map((d) => ({ path: d })), - }; -} diff --git a/tests/fs.test.ts b/tests/fs.test.ts deleted file mode 100644 index 11dc4f9..0000000 --- a/tests/fs.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { createFixture } from "fs-fixture"; -import { describe, expect, it } from "vitest"; -import { normalizeFileChanges } from "../src/fs.ts"; - -describe("normalizeFileChanges", () => { - it("should convert file contents to base64", async () => { - await using fixture = await createFixture({ - "foo.txt": "Hello, world!", - }); - - const result = await normalizeFileChanges( - { - additions: ["foo.txt"], - deletions: ["bar.txt"], - }, - fixture.path, - ); - - expect(result).toEqual({ - additions: [ - { - path: "foo.txt", - contents: await fixture.readFile("foo.txt", "base64"), - }, - ], - deletions: [{ path: "bar.txt" }], - }); - }); - - it("should pass through empty file changes", async () => { - const result = await normalizeFileChanges( - { additions: [], deletions: [] }, - "/", - ); - - expect(result).toEqual({ additions: [], deletions: [] }); - }); -}); diff --git a/tests/index.test.ts b/tests/index.test.ts new file mode 100644 index 0000000..38193c0 --- /dev/null +++ b/tests/index.test.ts @@ -0,0 +1,7 @@ +import { expect, it } from "vitest"; +import * as indexBrowser from "../src/index-browser.ts"; +import * as indexNode from "../src/index-node.ts"; + +it("should export the same functions in both browser and node versions", () => { + expect(Object.keys(indexBrowser)).toEqual(Object.keys(indexNode)); +}); diff --git a/tsdown.config.ts b/tsdown.config.ts index 3e922b8..c8cafbd 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -3,16 +3,10 @@ import { defineConfig } from "tsdown/config"; const isCi = process.env.CI != null; export default defineConfig({ - entry: [ - "src/index.ts", - "src/core.ts", - "src/git.ts", - "src/fs.ts", - "src/node.ts", - ], + entry: ["src/index-browser.ts", "src/index-node.ts"], outDir: "dist", hash: false, - exports: true, + exports: false, // useful for running `build --watch` and `test` concurrently clean: !process.argv.includes("--watch"), deps: {