Use parseEnv instead of dotenv and avoid side effects by bluwy · Pull Request #1947 · changesets/changesets · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/late-animals-drive.md
5 changes: 5 additions & 0 deletions .changeset/tricky-spies-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@changesets/get-github-info": patch
---

Automatically load `GITHUB_` environment variables from `.env` file
31 changes: 25 additions & 6 deletions packages/changelog-github/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { parseEnv } from "node:util";
import fs from "node:fs/promises";
import path from "node:path";
import type { ChangelogFunctions } from "@changesets/types";
import { config } from "dotenv";
import { getInfo, getInfoFromPullRequest } from "@changesets/get-github-info";

config();

// "match what you skip, capture what you want": the left alternative
// consumes markdown links so the right alternative only matches bare refs
function linkifyIssueRefs(
Expand All @@ -17,9 +17,28 @@ function linkifyIssueRefs(
);
}

function readEnv() {
async function readEnvFile() {
const envFile = path.resolve(process.cwd(), ".env");
let content: string | undefined;
try {
content = await fs.readFile(envFile, "utf-8");
} catch {
return {};
}
return parseEnv(content);
}

let cachedEnv: ReturnType<typeof readEnvFile> | undefined;
function readEnvFileCached() {
cachedEnv ??= readEnvFile();
return cachedEnv;
}

async function readEnv() {
const GITHUB_SERVER_URL =
process.env.GITHUB_SERVER_URL || "https://github.com";
process.env.GITHUB_SERVER_URL ||
(await readEnvFileCached()).GITHUB_SERVER_URL ||
"https://github.com";
return { GITHUB_SERVER_URL };
}

Expand Down Expand Up @@ -59,7 +78,7 @@ const changelogFunctions: ChangelogFunctions = {
return [changesetLink, ...updatedDepenenciesList].join("\n");
},
getReleaseLine: async (changeset, type, options) => {
const { GITHUB_SERVER_URL } = readEnv();
const { GITHUB_SERVER_URL } = await readEnv();
if (!options || !options.repo) {
throw new Error(
'Please provide a repo to this changelog generator like this:\n"changelog": ["@changesets/changelog-github", { "repo": "org/repo" }]',
Expand Down
20 changes: 3 additions & 17 deletions packages/get-github-info/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,11 @@

> Note: This assumes you already have changesets setup.

To use `@changesets/get-github-info`, you'll need to install it and you'll probably also want `dotenv` to provide a GitHub personal access token via a `.env` file.
You can use `@changesets/get-github-info` like this if you have a [custom changelog formatter](https://github.com/changesets/changesets/blob/main/docs/modifying-changelog-format.md).

```bash
yarn add --dev @changesets/get-github-info dotenv
```

or

```bash
npm install --save-dev @changesets/get-github-info dotenv
```

Then you can use it in your `.changeset/config.js` like this.

```jsx
import dotenv from "dotenv";
```js
import { getInfo } from "@changesets/get-github-info";

dotenv.config();
// ...

const getReleaseLine = async (changeset, type) => {
Expand All @@ -53,7 +39,7 @@ const getReleaseLine = async (changeset, type) => {
// ...
```

You'll need to [get a GitHub personal access token](https://github.com/settings/tokens/new?scopes=read:user,repo:status&description=changesets) with `read:user` and `repo:status` permissions, and add it to a `.env` file.
You'll need to [get a GitHub personal access token](https://github.com/settings/tokens/new?scopes=read:user,repo:status&description=changesets) with `read:user` and `repo:status` permissions, and add it to a `.env` file (it'll be loaded automatically).

```bash
GITHUB_TOKEN=token_here
Expand Down
46 changes: 33 additions & 13 deletions packages/get-github-info/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
import DataLoader from "dataloader";
import { parseEnv } from "node:util";
import fs from "node:fs/promises";
import path from "node:path";

function readEnv() {
async function readEnvFile() {
const envFile = path.resolve(process.cwd(), ".env");
let content: string | undefined;
try {
content = await fs.readFile(envFile, "utf-8");
} catch {
return {};
}
return parseEnv(content);
}

let cachedEnv: ReturnType<typeof readEnvFile> | undefined;
function readEnvFileCached() {
cachedEnv ??= readEnvFile();
return cachedEnv;
}

async function readEnv() {
const GITHUB_GRAPHQL_URL =
process.env.GITHUB_GRAPHQL_URL || "https://api.github.com/graphql";
process.env.GITHUB_GRAPHQL_URL ||
(await readEnvFileCached()).GITHUB_GRAPHQL_URL ||
"https://api.github.com/graphql";
const GITHUB_SERVER_URL =
process.env.GITHUB_SERVER_URL || "https://github.com";
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
process.env.GITHUB_SERVER_URL ||
(await readEnvFileCached()).GITHUB_SERVER_URL ||
"https://github.com";
const GITHUB_TOKEN =
process.env.GITHUB_TOKEN || (await readEnvFileCached()).GITHUB_TOKEN;
return { GITHUB_GRAPHQL_URL, GITHUB_SERVER_URL, GITHUB_TOKEN };
}

Expand Down Expand Up @@ -33,9 +58,7 @@ function makeQuery(repos: ReposWithCommitsAndPRsToFetch) {
${repos[repo]
.map((data) =>
data.kind === "commit"
? `a${data.commit}: object(expression: ${JSON.stringify(
data.commit,
)}) {
? `a${data.commit}: object(expression: ${JSON.stringify(data.commit)}) {
... on Commit {
commitUrl
associatedPullRequests(first: 50) {
Expand Down Expand Up @@ -86,7 +109,8 @@ function makeQuery(repos: ReposWithCommitsAndPRsToFetch) {
// getReleaseLine will be called a large number of times but it'll be called at the same time
// so instead of doing a bunch of network requests, we can do a single one.
const GHDataLoader = new DataLoader(async (requests: RequestData[]) => {
const { GITHUB_GRAPHQL_URL, GITHUB_SERVER_URL, GITHUB_TOKEN } = readEnv();
const { GITHUB_GRAPHQL_URL, GITHUB_SERVER_URL, GITHUB_TOKEN } =
await readEnv();
if (!GITHUB_TOKEN) {
throw new Error(
`Please create a GitHub personal access token at ${GITHUB_SERVER_URL}/settings/tokens/new?scopes=read:user,repo:status&description=changesets-${new Date()
Expand Down Expand Up @@ -129,11 +153,7 @@ const GHDataLoader = new DataLoader(async (requests: RequestData[]) => {

if (data.errors) {
throw new Error(
`Fetched data from GitHub returned errors\n${JSON.stringify(
data.errors,
null,
2,
)}`,
`Fetched data from GitHub returned errors\n${JSON.stringify(data.errors, null, 2)}`,
);
}

Expand Down
5 changes: 0 additions & 5 deletions yarn.lock
Loading