-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5b109d9
commit fba96db
Showing
5 changed files
with
137 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
|
@@ -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; | ||
|
@@ -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."); | ||
|
@@ -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) { | ||
|
@@ -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; | ||
} | ||
} | ||
|
@@ -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" | ||
); | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.