mirror of
https://github.com/electron/electron.git
synced 2026-05-02 03:00:22 -04:00
* build: add oxfmt for code formatting and import sorting
Adds oxfmt as a devDependency alongside oxlint and wires it into the
lint pipeline. The .oxfmtrc.json config matches Electron's current JS
style (single quotes, semicolons, 2-space indent, trailing commas off,
printWidth 100) and configures sortImports with custom groups that
mirror the import/order pathGroups previously enforced by ESLint:
@electron/internal, @electron/*, and {electron,electron/**} each get
their own ordered group ahead of external modules.
- `yarn lint:fmt` runs `oxfmt --check` over JS/TS sources and is
chained into `yarn lint` so CI enforces it automatically.
- `yarn format` runs `oxfmt --write` for local fix-up.
- lint-staged invokes `oxfmt --write` on staged .js/.ts/.mjs/.cjs
files before oxlint, so formatting is applied at commit time.
The next commit applies the formatter to the existing codebase so the
check actually passes.
* chore: apply oxfmt formatting to JS and TS sources
Runs `yarn format` across lib/, spec/, script/, build/, default_app/,
and npm/ to bring the codebase in line with the .oxfmtrc.json settings
added in the previous commit. This is a pure formatting pass: import
statements are sorted into the groups defined by the config, method
chains longer than printWidth are broken, single-quoted strings
containing apostrophes are switched to double quotes, and a handful of
single-statement `if` bodies are re-wrapped and get braces added by
`oxlint --fix` to satisfy the `curly: multi-line` rule.
No behavior changes.
192 lines
6.7 KiB
TypeScript
Executable File
192 lines
6.7 KiB
TypeScript
Executable File
import { Octokit } from '@octokit/rest';
|
|
import * as chalk from 'chalk';
|
|
|
|
import { execSync, spawnSync } from 'node:child_process';
|
|
import { join } from 'node:path';
|
|
|
|
import { getCurrentBranch, ELECTRON_DIR } from '../lib/utils.js';
|
|
import { createGitHubTokenStrategy } from './github-token';
|
|
import releaseNotesGenerator from './notes';
|
|
import { runReleaseCIJobs } from './run-release-ci-jobs';
|
|
import { ELECTRON_ORG, ElectronReleaseRepo, VersionBumpType } from './types';
|
|
|
|
const pass = chalk.green('✓');
|
|
const fail = chalk.red('✗');
|
|
|
|
enum DryRunMode {
|
|
DRY_RUN,
|
|
REAL_RUN
|
|
}
|
|
|
|
type PrepareReleaseOptions = {
|
|
targetRepo: ElectronReleaseRepo;
|
|
targetBranch?: string;
|
|
bumpType: VersionBumpType;
|
|
isPreRelease: boolean;
|
|
};
|
|
|
|
async function getNewVersion(options: PrepareReleaseOptions, dryRunMode: DryRunMode) {
|
|
if (dryRunMode === DryRunMode.REAL_RUN) {
|
|
console.log(`Bumping for new "${options.bumpType}" version.`);
|
|
}
|
|
const bumpScript = join(__dirname, 'version-bumper.ts');
|
|
const scriptArgs = ['node', 'node_modules/.bin/ts-node', bumpScript, `--bump=${options.bumpType}`];
|
|
if (dryRunMode === DryRunMode.DRY_RUN) scriptArgs.push('--dryRun');
|
|
try {
|
|
let bumpVersion = execSync(scriptArgs.join(' '), { encoding: 'utf-8' });
|
|
bumpVersion = bumpVersion.substr(bumpVersion.indexOf(':') + 1).trim();
|
|
const newVersion = `v${bumpVersion}`;
|
|
if (dryRunMode === DryRunMode.REAL_RUN) {
|
|
console.log(`${pass} Successfully bumped version to ${newVersion}`);
|
|
}
|
|
return newVersion;
|
|
} catch (err) {
|
|
console.log(`${fail} Could not bump version, error was:`, err);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
async function getReleaseNotes(options: PrepareReleaseOptions, currentBranch: string, newVersion: string) {
|
|
if (options.bumpType === 'nightly') {
|
|
return {
|
|
text: 'Nightlies do not get release notes, please compare tags for info.'
|
|
};
|
|
}
|
|
console.log(`Generating release notes for ${currentBranch}.`);
|
|
const releaseNotes = await releaseNotesGenerator(currentBranch, newVersion);
|
|
if (releaseNotes.warning) {
|
|
console.warn(releaseNotes.warning);
|
|
}
|
|
return releaseNotes;
|
|
}
|
|
|
|
async function createRelease(options: PrepareReleaseOptions, branchToTarget: string) {
|
|
const newVersion = await getNewVersion(options, DryRunMode.REAL_RUN);
|
|
const releaseNotes = await getReleaseNotes(options, branchToTarget, newVersion);
|
|
await tagRelease(newVersion);
|
|
|
|
const octokit = new Octokit({
|
|
authStrategy: createGitHubTokenStrategy(options.targetRepo)
|
|
});
|
|
|
|
console.log('Checking for existing draft release.');
|
|
const releases = await octokit.repos
|
|
.listReleases({
|
|
owner: ELECTRON_ORG,
|
|
repo: options.targetRepo
|
|
})
|
|
.catch((err) => {
|
|
console.log(`${fail} Could not get releases. Error was: `, err);
|
|
throw err;
|
|
});
|
|
|
|
const drafts = releases.data.filter((release) => release.draft && release.tag_name === newVersion);
|
|
if (drafts.length > 0) {
|
|
console.log(`${fail} Aborting because draft release for
|
|
${drafts[0].tag_name} already exists.`);
|
|
process.exit(1);
|
|
}
|
|
console.log(`${pass} A draft release does not exist; creating one.`);
|
|
|
|
let releaseBody;
|
|
let releaseIsPrelease = false;
|
|
if (options.isPreRelease) {
|
|
if (newVersion.indexOf('nightly') > 0) {
|
|
releaseBody =
|
|
'Note: This is a nightly release. Please file new issues ' +
|
|
'for any bugs you find in it.\n \n This release is published to npm ' +
|
|
'under the electron-nightly package and can be installed via `npm install electron-nightly`, ' +
|
|
`or \`npm install electron-nightly@${newVersion.substr(1)}\`.\n \n ${releaseNotes.text}`;
|
|
} else if (newVersion.indexOf('alpha') > 0) {
|
|
releaseBody =
|
|
'Note: This is an alpha release. Please file new issues ' +
|
|
'for any bugs you find in it.\n \n This release is published to npm ' +
|
|
'under the alpha tag and can be installed via `npm install electron@alpha`, ' +
|
|
`or \`npm install electron@${newVersion.substr(1)}\`.\n \n ${releaseNotes.text}`;
|
|
} else {
|
|
releaseBody =
|
|
'Note: This is a beta release. Please file new issues ' +
|
|
'for any bugs you find in it.\n \n This release is published to npm ' +
|
|
'under the beta tag and can be installed via `npm install electron@beta`, ' +
|
|
`or \`npm install electron@${newVersion.substr(1)}\`.\n \n ${releaseNotes.text}`;
|
|
}
|
|
releaseIsPrelease = true;
|
|
} else {
|
|
releaseBody = releaseNotes.text;
|
|
}
|
|
|
|
const release = await octokit.repos
|
|
.createRelease({
|
|
owner: ELECTRON_ORG,
|
|
repo: options.targetRepo,
|
|
tag_name: newVersion,
|
|
draft: true,
|
|
name: `electron ${newVersion}`,
|
|
body: releaseBody,
|
|
prerelease: releaseIsPrelease,
|
|
target_commitish: newVersion.includes('nightly') ? 'main' : branchToTarget
|
|
})
|
|
.catch((err) => {
|
|
console.log(`${fail} Error creating new release: `, err);
|
|
process.exit(1);
|
|
});
|
|
|
|
console.log(`Release has been created with id: ${release.data.id}.`);
|
|
console.log(`${pass} Draft release for ${newVersion} successful.`);
|
|
}
|
|
|
|
async function pushRelease(branch: string) {
|
|
const pushDetails = spawnSync('git', ['push', 'origin', `HEAD:${branch}`, '--follow-tags'], {
|
|
cwd: ELECTRON_DIR,
|
|
encoding: 'utf8',
|
|
stdio: ['inherit', 'pipe', 'pipe']
|
|
});
|
|
if (pushDetails.status === 0) {
|
|
console.log(
|
|
`${pass} Successfully pushed the release. Wait for ` +
|
|
'release builds to finish before running "npm run release".'
|
|
);
|
|
} else {
|
|
console.log(`${fail} Error pushing the release: ${pushDetails.stderr}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
async function runReleaseBuilds(branch: string, newVersion: string) {
|
|
await runReleaseCIJobs(branch, {
|
|
ci: undefined,
|
|
ghRelease: true,
|
|
newVersion
|
|
});
|
|
}
|
|
|
|
async function tagRelease(version: string) {
|
|
console.log(`Tagging release ${version}.`);
|
|
const checkoutDetails = spawnSync('git', ['tag', '-a', '-m', version, version], {
|
|
cwd: ELECTRON_DIR,
|
|
encoding: 'utf8',
|
|
stdio: ['inherit', 'pipe', 'pipe']
|
|
});
|
|
if (checkoutDetails.status === 0) {
|
|
console.log(`${pass} Successfully tagged ${version}.`);
|
|
} else {
|
|
console.log(`${fail} Error tagging ${version}: ` + `${checkoutDetails.stderr}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
export async function printNextVersion(options: PrepareReleaseOptions) {
|
|
const newVersion = await getNewVersion(options, DryRunMode.DRY_RUN);
|
|
console.log(newVersion);
|
|
}
|
|
|
|
export async function prepareRelease(options: PrepareReleaseOptions) {
|
|
const currentBranch = options.targetBranch || (await getCurrentBranch(ELECTRON_DIR));
|
|
|
|
const newVersion = await getNewVersion(options, DryRunMode.DRY_RUN);
|
|
console.log(`${pass} Starting release of ${newVersion}`);
|
|
await createRelease(options, currentBranch);
|
|
await pushRelease(currentBranch);
|
|
await runReleaseBuilds(currentBranch, newVersion);
|
|
}
|