Skip to content

chore: end-to-end test setup script #146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 23, 2022
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
15 changes: 15 additions & 0 deletions .github/workflows/setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Test Setup Script

on:
push:
branches:
- main
pull_request:

jobs:
setup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/prepare
- run: pnpm run setup:test
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"lint:spelling": "cspell \"**\" \".github/**/*\"",
"prepare": "husky install",
"setup": "npx --yes zx --quiet script/setup.js",
"setup:test": "npx --yes zx --quiet script/setup-test-e2e.js",
"test": "vitest"
},
"type": "module",
Expand Down
21 changes: 21 additions & 0 deletions script/setup-test-e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* global $ */

import { strict as assert } from "node:assert";

import { promises as fs } from "fs";

const description = "New Description Test";
const owner = "NewOwnerTest";
const title = "New Title Test";
const repository = "new-repository-test";

const result =
await $`pnpm run setup --description ${description} --owner ${owner} --title ${title} --repository ${repository} --skip-api`;
console.log({ result });

const newPackageJson = JSON.parse(
(await fs.readFile("./package.json")).toString()
);

assert.equal(newPackageJson.description, description);
assert.equal(newPackageJson.name, repository);
173 changes: 93 additions & 80 deletions script/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,14 @@ try {
);
console.log();

console.log(chalk.gray`Checking gh auth status...`);
let auth;
try {
await $`gh auth status`;
auth = (await $`gh auth token`).toString().trim();
} catch (error) {
throw new Error(error.stderr);
}

console.log(chalk.gray`✔️ Done.`);
console.log();

const { values } = parseArgs({
args: process.argv.slice(2),
options: {
description: { type: "string" },
owner: { type: "string" },
repository: { type: "string" },
title: { type: "string" },
"skip-api": { type: "boolean" },
},
tokens: true,
strict: false,
Expand Down Expand Up @@ -80,6 +69,11 @@ try {
"How would you describe the new package?"
);

const skipApi = await getPrefillOrPromptedValue(
"skip-api",
"Whether to skip calling the GitHub API (effectively making this a local-only change)."
);

console.log();
console.log(chalk.gray`Hydrating package metadata locally...`);

Expand Down Expand Up @@ -118,6 +112,7 @@ try {
["JoshuaKGoldberg", owner],
["template-typescript-node-package", repository],
[/"setup": ".*",/, ``, "./package.json"],
[/"setup:test": ".*",/, ``, "./package.json"],
[
`"version": "${existingPackage.version}"`,
`"version": "0.0.0"`,
Expand Down Expand Up @@ -159,87 +154,105 @@ try {

console.log(chalk.gray`✔️ Done.`);

console.log(chalk.gray`✔️ Done.`);
console.log();
console.log(chalk.gray`Hydrating repository labels...`);

const existingLabels = JSON.parse(
(await $`gh label list --json name`).stdout || "[]"
);
if (skipApi) {
console.log(chalk.gray`➖ Skipping API hydration.`);
} else {
console.log(chalk.gray`Checking gh auth status...`);
let auth;
try {
await $`gh auth status`;
auth = (await $`gh auth token`).toString().trim();
} catch (error) {
throw new Error(error.stderr);
}

for (const outcome of outcomeLabels) {
const action = existingLabels.some(
(existing) => existing.name === outcome.name
)
? "edit"
: "create";
await $`gh label ${action} ${outcome.name} --color ${outcome.color} --description ${outcome.description}`;
}
console.log(chalk.gray`✔️ Done.`);
console.log();

console.log(chalk.gray`✔️ Done.`);
console.log(chalk.gray`Hydrating repository labels...`);

console.log();
console.log(chalk.gray`Hydrating initial repository settings...`);

const octokit = new Octokit({ auth });

octokit.rest.repos.update({
allow_auto_merge: true,
allow_rebase_merge: false,
allow_squash_merge: true,
default_branch: "main",
delete_branch_on_merge: true,
description,
has_wiki: false,
owner,
repo: repository,
});
const existingLabels = JSON.parse(
(await $`gh label list --json name`).stdout || "[]"
);

console.log();
console.log(chalk.gray`Hydrating branch protection settings...`);

// Note: keep this inline script in sync with .github/workflows/release.yml!
// Todo: it would be nice to not have two sources of truth...
// https://github.com/JoshuaKGoldberg/template-typescript-node-package/issues/145
await octokit.request(
`PUT /repos/${owner}/${repository}/branches/main/protection`,
{
allow_deletions: false,
allow_force_pushes: true,
allow_fork_pushes: false,
allow_fork_syncing: true,
block_creations: false,
branch: "main",
enforce_admins: false,
owner,
repo: repository,
required_conversation_resolution: true,
required_linear_history: false,
required_pull_request_reviews: null,
required_status_checks: {
checks: [
{ context: "build" },
{ context: "compliance" },
{ context: "lint" },
{ context: "markdown" },
{ context: "package" },
{ context: "packages" },
{ context: "prettier" },
{ context: "prune" },
{ context: "spelling" },
{ context: "test" },
],
strict: false,
},
restrictions: null,
for (const outcome of outcomeLabels) {
const action = existingLabels.some(
(existing) => existing.name === outcome.name
)
? "edit"
: "create";
await $`gh label ${action} ${outcome.name} --color ${outcome.color} --description ${outcome.description}`;
}
);
console.log(chalk.gray`✔️ Done.`);

console.log(chalk.gray`✔️ Done.`);
console.log();
console.log(chalk.gray`Hydrating initial repository settings...`);

const octokit = new Octokit({ auth });

octokit.rest.repos.update({
allow_auto_merge: true,
allow_rebase_merge: false,
allow_squash_merge: true,
default_branch: "main",
delete_branch_on_merge: true,
description,
has_wiki: false,
owner,
repo: repository,
});

console.log();
console.log(chalk.gray`Hydrating branch protection settings...`);

// Note: keep this inline script in sync with .github/workflows/release.yml!
// Todo: it would be nice to not have two sources of truth...
// https://github.com/JoshuaKGoldberg/template-typescript-node-package/issues/145
await octokit.request(
`PUT /repos/${owner}/${repository}/branches/main/protection`,
{
allow_deletions: false,
allow_force_pushes: true,
allow_fork_pushes: false,
allow_fork_syncing: true,
block_creations: false,
branch: "main",
enforce_admins: false,
owner,
repo: repository,
required_conversation_resolution: true,
required_linear_history: false,
required_pull_request_reviews: null,
required_status_checks: {
checks: [
{ context: "build" },
{ context: "compliance" },
{ context: "lint" },
{ context: "markdown" },
{ context: "package" },
{ context: "packages" },
{ context: "prettier" },
{ context: "prune" },
{ context: "spelling" },
{ context: "test" },
],
strict: false,
},
restrictions: null,
}
);

console.log(chalk.gray`✔️ Done.`);
}

console.log();
console.log(chalk.gray`Removing setup script...`);

await fs.rm("./script", { force: true, recursive: true });
await fs.rm(".github/workflows/setup.yml");

console.log(chalk.gray`✔️ Done.`);
} catch (error) {
Expand Down