Skip to content

Commit 638993f

Browse files
committed
feat(ng-dev): support ESM-written repository configurations
Adds support for ESM-written repository configurations. As part of this the `getConfig` method is now asynchronous. This commit adds the necessary `await` statement where needed and makes this more type-safe to ensure the `await` is not accidentally missing.
1 parent 7c752f6 commit 638993f

File tree

66 files changed

+856
-486
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+856
-486
lines changed

github-actions/commit-message-based-labels/main.js

Lines changed: 279 additions & 38 deletions
Large diffs are not rendered by default.

github-actions/slash-commands/main.js

Lines changed: 119 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -60973,24 +60973,8 @@ function getCommitsInRange(from, to = "HEAD") {
6097360973
}
6097460974

6097560975
//
60976-
var import_typed_graphqlify = __toESM(require_dist());
60977-
var findOwnedForksOfRepoQuery = (0, import_typed_graphqlify.params)({
60978-
$owner: "String!",
60979-
$name: "String!"
60980-
}, {
60981-
repository: (0, import_typed_graphqlify.params)({ owner: "$owner", name: "$name" }, {
60982-
forks: (0, import_typed_graphqlify.params)({ affiliations: "OWNER", first: 1 }, {
60983-
nodes: [
60984-
{
60985-
owner: {
60986-
login: import_typed_graphqlify.types.string
60987-
},
60988-
name: import_typed_graphqlify.types.string
60989-
}
60990-
]
60991-
})
60992-
})
60993-
});
60976+
import tsNode from "ts-node";
60977+
import { dirname, join } from "path";
6099460978

6099560979
//
6099660980
var ANSI_BACKGROUND_OFFSET = 10;
@@ -61468,91 +61452,13 @@ var DryRunError = class extends Error {
6146861452
}
6146961453
};
6147061454

61471-
//
61472-
import tsNode from "ts-node";
61473-
import { dirname, join } from "path";
61474-
61475-
//
61476-
var cachedConfig = null;
61477-
function setCachedConfig(config) {
61478-
cachedConfig = config;
61479-
}
61480-
function getCachedConfig() {
61481-
return cachedConfig;
61482-
}
61483-
61484-
//
61485-
var CONFIG_FILE_PATH = ".ng-dev/config";
61486-
var setConfig = setCachedConfig;
61487-
function getConfig(baseDirOrAssertions) {
61488-
let cachedConfig2 = getCachedConfig();
61489-
if (cachedConfig2 === null) {
61490-
let baseDir;
61491-
if (typeof baseDirOrAssertions === "string") {
61492-
baseDir = baseDirOrAssertions;
61493-
} else {
61494-
baseDir = GitClient.get().baseDir;
61495-
}
61496-
const configPath = join(baseDir, CONFIG_FILE_PATH);
61497-
cachedConfig2 = readConfigFile(configPath);
61498-
setCachedConfig(cachedConfig2);
61499-
}
61500-
if (Array.isArray(baseDirOrAssertions)) {
61501-
for (const assertion of baseDirOrAssertions) {
61502-
assertion(cachedConfig2);
61503-
}
61504-
}
61505-
return __spreadValues({}, cachedConfig2);
61506-
}
61507-
var ConfigValidationError = class extends Error {
61508-
constructor(message, errors = []) {
61509-
super(message);
61510-
this.errors = errors;
61511-
}
61512-
};
61513-
function assertValidGithubConfig(config) {
61514-
const errors = [];
61515-
if (config.github === void 0) {
61516-
errors.push(`Github repository not configured. Set the "github" option.`);
61517-
} else {
61518-
if (config.github.name === void 0) {
61519-
errors.push(`"github.name" is not defined`);
61520-
}
61521-
if (config.github.owner === void 0) {
61522-
errors.push(`"github.owner" is not defined`);
61523-
}
61524-
}
61525-
if (errors.length) {
61526-
throw new ConfigValidationError("Invalid `github` configuration", errors);
61527-
}
61528-
}
61529-
function readConfigFile(configPath, returnEmptyObjectOnError = false) {
61530-
tsNode.register({
61531-
dir: dirname(configPath),
61532-
transpileOnly: true,
61533-
compilerOptions: { module: "commonjs" }
61534-
});
61535-
try {
61536-
return __require(configPath);
61537-
} catch (e2) {
61538-
if (returnEmptyObjectOnError) {
61539-
Log.debug(`Could not read configuration file at ${configPath}, returning empty object instead.`);
61540-
Log.debug(e2);
61541-
return {};
61542-
}
61543-
Log.error(`Could not read configuration file at ${configPath}.`);
61544-
Log.error(e2);
61545-
process.exit(1);
61546-
}
61547-
}
61548-
6154961455
//
6155061456
import { spawnSync } from "child_process";
6155161457

6155261458
//
6155361459
var import_graphql = __toESM(require_dist_node6());
6155461460
var import_rest3 = __toESM(require_dist_node12());
61555-
var import_typed_graphqlify2 = __toESM(require_dist());
61461+
var import_typed_graphqlify = __toESM(require_dist());
6155661462
var GithubClient = class {
6155761463
constructor(_octokitOptions) {
6155861464
this._octokitOptions = _octokitOptions;
@@ -61574,7 +61480,7 @@ var AuthenticatedGithubClient = class extends GithubClient {
6157461480
this._graphql = import_graphql.graphql.defaults({ headers: { authorization: `token ${this._token}` } });
6157561481
}
6157661482
async graphql(queryObject, params4 = {}) {
61577-
return await this._graphql((0, import_typed_graphqlify2.query)(queryObject).toString(), params4);
61483+
return await this._graphql((0, import_typed_graphqlify.query)(queryObject).toString(), params4);
6157861484
}
6157961485
};
6158061486

@@ -61606,11 +61512,10 @@ var GitCommandError = class extends Error {
6160661512
}
6160761513
};
6160861514
var GitClient = class {
61609-
constructor(baseDir = determineRepoBaseDirFromCwd(), config = getConfig(baseDir)) {
61515+
constructor(config, baseDir = determineRepoBaseDirFromCwd()) {
6161061516
this.baseDir = baseDir;
6161161517
this.github = new GithubClient();
6161261518
this.gitBinPath = "git";
61613-
assertValidGithubConfig(config);
6161461519
this.config = config;
6161561520
this.remoteConfig = config.github;
6161661521
this.remoteParams = { owner: config.github.owner, repo: config.github.name };
@@ -61692,13 +61597,16 @@ var GitClient = class {
6169261597
sanitizeConsoleOutput(value) {
6169361598
return value;
6169461599
}
61695-
static get() {
61696-
if (!this._unauthenticatedInstance) {
61697-
GitClient._unauthenticatedInstance = new GitClient();
61600+
static async get() {
61601+
if (GitClient._unauthenticatedInstance === null) {
61602+
GitClient._unauthenticatedInstance = (async () => {
61603+
return new GitClient(await getConfig([assertValidGithubConfig]));
61604+
})();
6169861605
}
6169961606
return GitClient._unauthenticatedInstance;
6170061607
}
6170161608
};
61609+
GitClient._unauthenticatedInstance = null;
6170261610
function gitOutputAsArray(gitCommandResult) {
6170361611
return gitCommandResult.stdout.split("\n").map((x2) => x2.trim()).filter((x2) => !!x2);
6170461612
}
@@ -61776,10 +61684,104 @@ function printToLogFile(logLevel, ...text) {
6177661684
`).join("");
6177761685
}
6177861686

61687+
//
61688+
var cachedConfig = null;
61689+
function setCachedConfig(config) {
61690+
cachedConfig = config;
61691+
}
61692+
function getCachedConfig() {
61693+
return cachedConfig;
61694+
}
61695+
61696+
//
61697+
var CONFIG_FILE_PATH = ".ng-dev/config.mjs";
61698+
var setConfig = setCachedConfig;
61699+
async function getConfig(baseDirOrAssertions) {
61700+
let cachedConfig2 = getCachedConfig();
61701+
if (cachedConfig2 === null) {
61702+
let baseDir;
61703+
if (typeof baseDirOrAssertions === "string") {
61704+
baseDir = baseDirOrAssertions;
61705+
} else {
61706+
baseDir = determineRepoBaseDirFromCwd();
61707+
}
61708+
const configPath = join(baseDir, CONFIG_FILE_PATH);
61709+
cachedConfig2 = await readConfigFile(configPath);
61710+
setCachedConfig(cachedConfig2);
61711+
}
61712+
if (Array.isArray(baseDirOrAssertions)) {
61713+
for (const assertion of baseDirOrAssertions) {
61714+
assertion(cachedConfig2);
61715+
}
61716+
}
61717+
return __spreadProps(__spreadValues({}, cachedConfig2), { __isNgDevConfigObject: true });
61718+
}
61719+
var ConfigValidationError = class extends Error {
61720+
constructor(message, errors = []) {
61721+
super(message);
61722+
this.errors = errors;
61723+
}
61724+
};
61725+
function assertValidGithubConfig(config) {
61726+
const errors = [];
61727+
if (config.github === void 0) {
61728+
errors.push(`Github repository not configured. Set the "github" option.`);
61729+
} else {
61730+
if (config.github.name === void 0) {
61731+
errors.push(`"github.name" is not defined`);
61732+
}
61733+
if (config.github.owner === void 0) {
61734+
errors.push(`"github.owner" is not defined`);
61735+
}
61736+
}
61737+
if (errors.length) {
61738+
throw new ConfigValidationError("Invalid `github` configuration", errors);
61739+
}
61740+
}
61741+
async function readConfigFile(configPath, returnEmptyObjectOnError = false) {
61742+
tsNode.register({
61743+
dir: dirname(configPath),
61744+
esm: true,
61745+
transpileOnly: true
61746+
});
61747+
try {
61748+
return await import(configPath);
61749+
} catch (e2) {
61750+
if (returnEmptyObjectOnError) {
61751+
Log.debug(`Could not read configuration file at ${configPath}, returning empty object instead.`);
61752+
Log.debug(e2);
61753+
return {};
61754+
}
61755+
Log.error(`Could not read configuration file at ${configPath}.`);
61756+
Log.error(e2);
61757+
process.exit(1);
61758+
}
61759+
}
61760+
61761+
//
61762+
var import_typed_graphqlify2 = __toESM(require_dist());
61763+
var findOwnedForksOfRepoQuery = (0, import_typed_graphqlify2.params)({
61764+
$owner: "String!",
61765+
$name: "String!"
61766+
}, {
61767+
repository: (0, import_typed_graphqlify2.params)({ owner: "$owner", name: "$name" }, {
61768+
forks: (0, import_typed_graphqlify2.params)({ affiliations: "OWNER", first: 1 }, {
61769+
nodes: [
61770+
{
61771+
owner: {
61772+
login: import_typed_graphqlify2.types.string
61773+
},
61774+
name: import_typed_graphqlify2.types.string
61775+
}
61776+
]
61777+
})
61778+
})
61779+
});
61780+
6177961781
//
6178061782
var AuthenticatedGitClient = class extends GitClient {
61781-
constructor(githubToken, baseDir, config) {
61782-
super(baseDir, config);
61783+
constructor(githubToken, config, baseDir) {
61784+
super(config, baseDir);
6178361785
this.githubToken = githubToken;
6178461786
this._githubTokenRegex = new RegExp(this.githubToken, "g");
6178561787
this._cachedOauthScopes = null;
@@ -61838,19 +61840,26 @@ Alternatively, a new token can be created at: ${GITHUB_TOKEN_GENERATE_URL}
6183861840
return scopes.split(",").map((scope) => scope.trim()).filter((scope) => scope !== "");
6183961841
});
6184061842
}
61841-
static get() {
61842-
if (!AuthenticatedGitClient._authenticatedInstance) {
61843-
throw new Error("No instance of `AuthenticatedGitClient` has been set up yet.");
61843+
static async get() {
61844+
if (AuthenticatedGitClient._token === null) {
61845+
throw new Error("No instance of `AuthenticatedGitClient` has been configured.");
61846+
}
61847+
if (AuthenticatedGitClient._authenticatedInstance === null) {
61848+
AuthenticatedGitClient._authenticatedInstance = (async (token) => {
61849+
return new AuthenticatedGitClient(token, await getConfig([assertValidGithubConfig]));
61850+
})(AuthenticatedGitClient._token);
6184461851
}
6184561852
return AuthenticatedGitClient._authenticatedInstance;
6184661853
}
6184761854
static configure(token) {
6184861855
if (AuthenticatedGitClient._authenticatedInstance) {
6184961856
throw Error("Unable to configure `AuthenticatedGitClient` as it has been configured already.");
6185061857
}
61851-
AuthenticatedGitClient._authenticatedInstance = new AuthenticatedGitClient(token);
61858+
AuthenticatedGitClient._token = token;
6185261859
}
6185361860
};
61861+
AuthenticatedGitClient._token = null;
61862+
AuthenticatedGitClient._authenticatedInstance = null;
6185461863

6185561864
//
6185661865
var import_inquirer = __toESM(require_inquirer());
@@ -61972,7 +61981,7 @@ async function fetchPullRequestFromGithub(git, prNumber) {
6197261981

6197361982
//
6197461983
async function rebasePr(prNumber, githubToken) {
61975-
const git = AuthenticatedGitClient.get();
61984+
const git = await AuthenticatedGitClient.get();
6197661985
if (git.hasUncommittedChanges()) {
6197761986
Log.error("Cannot perform rebase of PR with local changes.");
6197861987
return 1;

ng-dev/caretaker/check/base.spec.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8+
import {AuthenticatedGitClient} from '../../utils/git/authenticated-git-client.js';
89
import {installVirtualGitClientSpies} from '../../utils/testing/index.js';
910
import {BaseModule} from './base.js';
1011

@@ -21,21 +22,23 @@ class ConcreteBaseModule extends BaseModule<typeof exampleData> {
2122

2223
describe('BaseModule', () => {
2324
let retrieveDataSpy: jasmine.Spy;
25+
let git: AuthenticatedGitClient;
2426

25-
beforeEach(() => {
27+
beforeEach(async () => {
2628
retrieveDataSpy = spyOn(ConcreteBaseModule.prototype, 'retrieveData');
2729
installVirtualGitClientSpies();
30+
git = await AuthenticatedGitClient.get();
2831
});
2932

3033
it('begins retrieving data during construction', () => {
31-
new ConcreteBaseModule({} as any);
34+
new ConcreteBaseModule(git, {} as any);
3235

3336
expect(retrieveDataSpy).toHaveBeenCalled();
3437
});
3538

3639
it('makes the data available via the data attribute', async () => {
3740
retrieveDataSpy.and.callThrough();
38-
const module = new ConcreteBaseModule({} as any);
41+
const module = new ConcreteBaseModule(git, {} as any);
3942

4043
expect(await module.data).toBe(exampleData);
4144
});

ng-dev/caretaker/check/base.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ import {CaretakerConfig} from '../config.js';
1212

1313
/** The BaseModule to extend modules for caretaker checks from. */
1414
export abstract class BaseModule<Data> {
15-
/** The singleton instance of the authenticated git client. */
16-
protected git = AuthenticatedGitClient.get();
1715
/** The data for the module. */
1816
readonly data = this.retrieveData();
1917

20-
constructor(protected config: {caretaker: CaretakerConfig; github: GithubConfig}) {}
18+
constructor(
19+
protected git: AuthenticatedGitClient,
20+
protected config: {caretaker: CaretakerConfig; github: GithubConfig},
21+
) {}
2122

2223
/** Asyncronously retrieve data for the module. */
2324
protected abstract retrieveData(): Promise<Data>;

ng-dev/caretaker/check/check.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
import {AuthenticatedGitClient} from '../../utils/git/authenticated-git-client.js';
910
import {assertValidGithubConfig, getConfig} from '../../utils/config.js';
1011
import {assertValidCaretakerConfig} from '../config.js';
1112

@@ -20,11 +21,15 @@ const moduleList = [GithubQueriesModule, ServicesModule, CiModule, G3Module];
2021
/** Check the status of services which Angular caretakers need to monitor. */
2122
export async function checkServiceStatuses() {
2223
/** The configuration for the caretaker commands. */
23-
const config = getConfig();
24+
const config = await getConfig();
2425
assertValidCaretakerConfig(config);
2526
assertValidGithubConfig(config);
27+
28+
/** An authenticated git client instance. */
29+
const git = await AuthenticatedGitClient.get();
30+
2631
/** List of instances of Caretaker Check modules */
27-
const caretakerCheckModules = moduleList.map((module) => new module(config));
32+
const caretakerCheckModules = moduleList.map((module) => new module(git, config));
2833

2934
// Module's `data` is casted as Promise<unknown> because the data types of the `module`'s `data`
3035
// promises do not match typings, however our usage here is only to determine when the promise

0 commit comments

Comments
 (0)