Skip to content

Commit

Permalink
Fix: Prepare publish (#212)
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin authored Feb 5, 2024
1 parent 5b109d9 commit fba96db
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 85 deletions.
4 changes: 2 additions & 2 deletions eng/scripts/check-for-changed-files.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { checkForChangedFiles, coreRepoRoot, repoRoot } from "./helpers.js";

if (
checkForChangedFiles(coreRepoRoot, "## typespec ##") ||
checkForChangedFiles(repoRoot, "## typespec-azure ##")
(await checkForChangedFiles(coreRepoRoot, "## typespec ##")) ||
(await checkForChangedFiles(repoRoot, "## typespec-azure ##"))
) {
if (process.argv[2] !== "publish") {
console.error(
Expand Down
2 changes: 1 addition & 1 deletion eng/scripts/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function scanSwaggers(root) {
return files;
}

export function checkForChangedFiles(cwd, comment = undefined, options = {}) {
export async function checkForChangedFiles(cwd, comment = undefined, options = {}) {
if (comment && !options.silent) {
console.log();
console.log(comment);
Expand Down
207 changes: 126 additions & 81 deletions eng/scripts/prepare-publish.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// @ts-check
import { mkdirSync, writeFileSync } from "fs";
import { join } from "path";
import pc from "picocolors";
import { parseArgs } from "util";
import { runOrExit } from "../../core/packages/internal-build-utils/dist/src/common.js";
import {
CommandFailedError,
Expand All @@ -10,6 +12,33 @@ import {
repoRoot,
} from "./helpers.js";

const columns = process.stdout.columns;
function log(...args) {
console.log(...args);
}

function logSuccess(message) {
log(pc.green(`✓ ${message}`));
}

function logRegionStart(text) {
const split = Math.floor((columns - text.length - 4) / 2);
log();
log(pc.cyan("-".repeat(split) + " " + text + " " + "-".repeat(split)));
}

function logRegionEnd() {
log(pc.cyan("-".repeat(columns)));
}

const args = parseArgs({
options: {
noCommit: { type: "boolean" },
onlyBumpVersions: { type: "boolean" }, // Only bump version, skip any extra steps like updating the docs and regenerating samples
},
args: process.argv.slice(2),
});

const NoChange = 0;
const Patch = 1;
const Minor = 2;
Expand All @@ -19,60 +48,64 @@ const Major = 3;
* Set this to false to test this script without creating a new branch, checking for changes etc.
* DO NOT LEAVE TO FALSE
*/
const production = true;
const production = !args.values.noCommit;

let branch;

if (production) {
// Create and checkout branches
branch = `publish/${Date.now().toString(36)}`;
doubleRun("git", "checkout", "-b", branch);
log("Creating branch in both repos", branch);
await doubleRun("git", "checkout", "-b", branch);
}

// Check that we have a clean slate before starting
if (production) {
checkPrePublishState();
await checkPrePublishState();
}

// Update the typespec core submodule
typespecRun("git", "fetch", "https://github.com/microsoft/typespec", "main");
log("Updating typespec core submodule");
await typespecRun("git", "fetch", "https://github.com/microsoft/typespec", "main");
if (production) {
typespecRun("git", "merge", "--ff-only", "FETCH_HEAD");
await typespecRun("git", "merge", "--ff-only", "FETCH_HEAD");
}
// Stage the typespec core publish
typespecRun("pnpm", "change", "version");
typespecRun("pnpm", "update-latest-docs");
typespecRunWithRetries(3, "pnpm", "install");
if (production) {
typespecRun("git", "add", "-A");
await typespecRun("pnpm", "change", "version");
if (!args.values.onlyBumpVersions) {
await typespecRun("pnpm", "update-latest-docs");
}
if (checkForChangedFiles(coreRepoRoot, undefined, { silent: true })) {
await typespecRunWithRetries(3, "pnpm", "install");

if (await checkForChangedFiles(coreRepoRoot, undefined, { silent: true })) {
if (production) {
typespecRun("git", "commit", "-m", "Prepare typespec publish");
await typespecRun("git", "add", "-A");
await typespecRun("git", "commit", "-m", "Prepare typespec publish");
}
} else {
console.log("INFO: No changes to typespec.");
}

if (production && checkForChangedFiles(repoRoot, undefined, { silent: true })) {
typespecAzureRun("git", "commit", "-a", "-m", "Update core submodule");
if (production && (await checkForChangedFiles(repoRoot, undefined, { silent: true }))) {
await typespecAzureRun("git", "commit", "-a", "-m", "Update core submodule");
}

log("Bumping cross-submodule dependencies");
// Determine project versions including any bumps from typespec publish above
const versions = await getProjectVersions();

// Bump typespec-azure -> typespec dependencies.
await bumpCrossSubmoduleDependencies();

// Stage typespec-azure publish
typespecAzureRun("pnpm", "change", "version");
typespecAzureRun("pnpm", "update-latest-docs");
if (production) {
typespecAzureRun("git", "add", "-A");
await typespecAzureRun("pnpm", "change", "version");
if (!args.values.onlyBumpVersions) {
await typespecAzureRun("pnpm", "update-latest-docs");
}
if (checkForChangedFiles(repoRoot, undefined, { silent: true })) {
if (await checkForChangedFiles(repoRoot, undefined, { silent: true })) {
if (production) {
typespecAzureRun("git", "commit", "-m", "Prepare typespec-azure publish");
await typespecAzureRun("git", "add", "-A");
await typespecAzureRun("git", "commit", "-m", "Prepare typespec-azure publish");
}
} else {
console.log("INFO: No changes to typespec-azure.");
Expand All @@ -89,15 +122,16 @@ if (production) {
console.log("**DEVELOPMENT** The production flag is set to false");
}

function checkPrePublishState() {
if (checkForChangedFiles()) {
async function checkPrePublishState() {
log("Checking repo state is clean");
if (await checkForChangedFiles()) {
console.error("ERROR: Cannot prepare publish because files above were modified.");
process.exit(1);
}

try {
if (production) {
doubleRun("pnpm", "change", "status");
await doubleRun("pnpm", "change", "status");
}
} catch (e) {
if (e instanceof CommandFailedError) {
Expand All @@ -106,53 +140,57 @@ function checkPrePublishState() {
}
throw e;
}

logSuccess("Repo state is clean");
}

function doubleRun(command, ...args) {
typespecRun(command, ...args);
typespecAzureRun(command, ...args);
async function doubleRun(command, ...args) {
await typespecRun(command, ...args);
await typespecAzureRun(command, ...args);
}

function typespecRun(command, ...args) {
async function typespecRun(command, ...args) {
console.log();
console.log("## typespec ##");
runOrExit(command, args, { cwd: coreRepoRoot });
logRegionStart("typespec");
await runOrExit(command, args, { cwd: coreRepoRoot });
logRegionEnd();
}

function typespecAzureRun(command, ...args) {
async function typespecAzureRun(command, ...args) {
console.log();
console.log("## typespec-azure ##");
runOrExit(command, args, { cwd: repoRoot });
logRegionStart("typespec-azure");
await runOrExit(command, args, { cwd: repoRoot });
logRegionEnd();
}

function typespecAzureRunWithOptions(options, command, ...args) {
async function typespecAzureRunWithOptions(options, command, ...args) {
console.log();
console.log("## typespec-azure ##");
runOrExit(command, args, { cwd: repoRoot, ...options });
logRegionStart("typespec-azure");
await runOrExit(command, args, { cwd: repoRoot, ...options });
}

function typespecRunWithRetries(tries, command, ...args) {
async function typespecRunWithRetries(tries, command, ...args) {
try {
console.log();
console.log("## typespec ##");
console.log(`remaining tries: ${tries}`);
runOrExit(command, args, { cwd: coreRepoRoot });
logRegionStart(`typespec (remaining tries: ${tries})`);
await runOrExit(command, args, { cwd: coreRepoRoot });
logRegionEnd();
} catch (err) {
logRegionEnd();
if (tries-- > 0) {
typespecRunWithRetries(tries, command, ...args);
await typespecRunWithRetries(tries, command, ...args);
} else throw err;
}
}

function typespecAzureRunWithRetries(tries, command, ...args) {
async function typespecAzureRunWithRetries(tries, command, ...args) {
try {
console.log();
console.log("## typespec-azure ##");
console.log(`remaining tries: ${tries}`);
runOrExit(command, args, { cwd: repoRoot });
logRegionStart(`typespec-azure (remaining tries: ${tries})`);
await runOrExit(command, args, { cwd: repoRoot });
logRegionEnd();
} catch (err) {
logRegionEnd();
if (tries-- > 0) {
typespecAzureRunWithRetries(tries, command, ...args);
await typespecAzureRunWithRetries(tries, command, ...args);
} else throw err;
}
}
Expand All @@ -166,68 +204,75 @@ async function getProjectVersions() {
}

async function bumpCrossSubmoduleDependencies() {
logRegionStart("Bumping cross-submodule dependencies");
let changed = false;

for (const project of await listPackages()) {
if (project.dir.startsWith(coreRepoRoot)) {
return;
}
const packages = await listPackages();

for (const project of packages.filter((x) => !x.dir.startsWith(coreRepoRoot))) {
log("Checking if deps needs to be bump for project: ", project.manifest.name);

const pkgJson = { ...project.manifest };

const change = bumpDependencies(pkgJson);

const change = bumpDependencies(project);
if (change == NoChange) {
return;
continue;
}
logSuccess(`Project ${project.manifest.name} changed saving package.json.`);

writeFileSync(join(project.dir, "package.json"), JSON.stringify(project, undefined, 2) + "\n");
writeFileSync(join(project.dir, "package.json"), JSON.stringify(pkgJson, undefined, 2) + "\n");

if (project.manifest.private === false) {
return;
continue;
}

const changelog = {
changes: [
{
comment: "Update dependencies.",
type: change === Major ? "major" : change === Minor ? "minor" : "patch",
packageName: project.manifest.name,
},
],
packageName: project.manifest.name,
email: "[email protected]",
};

const changelogDir = join(repoRoot, "common/changes", project.manifest.name ?? "unknown");
const changelog = [
"---",
`"${project.manifest.name}": ${
change === Major ? "major" : change === Minor ? "minor" : "patch"
}`,
"---",
"Update dependencies.",
].join("\n");

const changelogDir = join(repoRoot, ".changesets");
mkdirSync(changelogDir, { recursive: true });

if (production) {
writeFileSync(
join(changelogDir, branch.replace("/", "-") + ".json"),
JSON.stringify(changelog, undefined, 2) + "\n"
);
writeFileSync(join(changelogDir, branch.replace("/", "-") + ".md"), changelog + "\n");
}

changed = true;
}
logRegionEnd();

if (changed && production) {
typespecAzureRun("git", "add", "-A");
typespecAzureRun("git", "commit", "-m", "Bump cross-submodule dependencies");
await typespecAzureRun("git", "add", "-A");
await typespecAzureRun("git", "commit", "-m", "Bump cross-submodule dependencies");
}
}

async function rebuildAndRegenSamplesToBumpTemplateVersions() {
typespecAzureRunWithRetries(3, "pnpm", "install");
typespecAzureRunWithOptions(
await typespecAzureRunWithRetries(3, "pnpm", "install");
await typespecAzureRunWithOptions(
{ env: { ...process.env, TYPESPEC_SKIP_DOCUSAURUS_BUILD: true } },
"pnpm",
"build"
);
typespecAzureRun("pnpm", "build");
typespecAzureRun("pnpm", "regen-samples");
if (!args.values.onlyBumpVersions) {
await typespecAzureRun("pnpm", "build");
await typespecAzureRun("pnpm", "regen-samples");
}

if (checkForChangedFiles(repoRoot, undefined, { silent: true }) && production) {
typespecAzureRun("git", "add", "-A");
typespecAzureRun("git", "commit", "-m", "Rebuild and regen samples to bump template versions");
if ((await checkForChangedFiles(repoRoot, undefined, { silent: true })) && production) {
await typespecAzureRun("git", "add", "-A");
await typespecAzureRun(
"git",
"commit",
"-m",
"Rebuild and regen samples to bump template versions"
);
}
}

Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"merge-coverage": "c8 -- report --reporter=cobertura --reporter=text",
"pack:all": "node ./eng/scripts/pack-all.js",
"preinstall": "npx only-allow pnpm",
"prepare-publish": "pnpm chronus version",
"prepare-publish": "node ./eng/scripts/prepare-publish.js",
"prettier": "prettier . --config .prettierrc.json",
"purge": "rimraf --glob \"packages/*/node_modules/\" --glob \"core/packages/*/node_modules/\"",
"regen-docs": "pnpm -r --parallel --aggregate-output --reporter=append-only run regen-docs",
Expand Down Expand Up @@ -50,5 +50,8 @@
"prod",
"resolutions"
]
},
"dependencies": {
"picocolors": "~1.0.0"
}
}
4 changes: 4 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fba96db

Please sign in to comment.