refactor(dev-infra): use shared github repo interface (#38656)
Instead of maintaining multiple interface for grouping owner name and repo name, we expose a shared interface describing a Github repository. One unfortunate downside is that the GraphQL Github and Rest API diverge slightly with the key for the repository name. i.e. rest uses `repo` for the name of a repository, while GraphQL uses `name` for the name. If that would be consistent, we could use the rest operator to pass a repository to the Octokit REST or GraphQL API. This does not work, so we have a small manual overhead as seen in the `branches.ts` file. PR Close #38656
This commit is contained in:
parent
3a598cf5ed
commit
d7ff8d765c
|
@ -7,16 +7,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as semver from 'semver';
|
import * as semver from 'semver';
|
||||||
import {GithubClient} from '../../../utils/git/github';
|
import {GithubClient, GithubRepo} from '../../../utils/git/github';
|
||||||
|
|
||||||
/** Type describing a Github repository with corresponding API client. */
|
/** Type describing a Github repository with corresponding API client. */
|
||||||
export interface GithubRepo {
|
export interface GithubRepoWithApi extends GithubRepo {
|
||||||
/** API client that can access the repository. */
|
/** API client that can access the repository. */
|
||||||
api: GithubClient;
|
api: GithubClient;
|
||||||
/** Owner login of the repository. */
|
|
||||||
owner: string;
|
|
||||||
/** Name of the repository. */
|
|
||||||
repo: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Type describing a version-branch. */
|
/** Type describing a version-branch. */
|
||||||
|
@ -51,7 +47,7 @@ const releaseTrainBranchNameRegex = /(\d+)\.(\d+)\.x/;
|
||||||
* a currently active feature-freeze/release-candidate release-train.
|
* a currently active feature-freeze/release-candidate release-train.
|
||||||
*/
|
*/
|
||||||
export async function fetchActiveReleaseTrainBranches(
|
export async function fetchActiveReleaseTrainBranches(
|
||||||
repo: GithubRepo, nextVersion: semver.SemVer): Promise<{
|
repo: GithubRepoWithApi, nextVersion: semver.SemVer): Promise<{
|
||||||
/** Release-train currently in active release-candidate/feature-freeze phase. */
|
/** Release-train currently in active release-candidate/feature-freeze phase. */
|
||||||
releaseCandidate: ReleaseTrain | null,
|
releaseCandidate: ReleaseTrain | null,
|
||||||
/** Latest non-prerelease release train (i.e. for the patch branch). */
|
/** Latest non-prerelease release train (i.e. for the patch branch). */
|
||||||
|
@ -102,9 +98,9 @@ export async function fetchActiveReleaseTrainBranches(
|
||||||
|
|
||||||
/** Gets the version of a given branch by reading the `package.json` upstream. */
|
/** Gets the version of a given branch by reading the `package.json` upstream. */
|
||||||
export async function getVersionOfBranch(
|
export async function getVersionOfBranch(
|
||||||
repo: GithubRepo, branchName: string): Promise<semver.SemVer> {
|
repo: GithubRepoWithApi, branchName: string): Promise<semver.SemVer> {
|
||||||
const {data} =
|
const {data} = await repo.api.repos.getContents(
|
||||||
await repo.api.repos.getContents({...repo, path: '/package.json', ref: branchName});
|
{owner: repo.owner, repo: repo.name, path: '/package.json', ref: branchName});
|
||||||
const {version} = JSON.parse(Buffer.from(data.content, 'base64').toString());
|
const {version} = JSON.parse(Buffer.from(data.content, 'base64').toString());
|
||||||
const parsedVersion = semver.parse(version);
|
const parsedVersion = semver.parse(version);
|
||||||
if (parsedVersion === null) {
|
if (parsedVersion === null) {
|
||||||
|
@ -136,8 +132,9 @@ export function getVersionForReleaseTrainBranch(branchName: string): semver.SemV
|
||||||
* order. i.e. latest version branches first.
|
* order. i.e. latest version branches first.
|
||||||
*/
|
*/
|
||||||
export async function getBranchesForMajorVersions(
|
export async function getBranchesForMajorVersions(
|
||||||
repo: GithubRepo, majorVersions: number[]): Promise<VersionBranch[]> {
|
repo: GithubRepoWithApi, majorVersions: number[]): Promise<VersionBranch[]> {
|
||||||
const {data: branchData} = await repo.api.repos.listBranches({...repo, protected: true});
|
const {data: branchData} =
|
||||||
|
await repo.api.repos.listBranches({owner: repo.owner, repo: repo.name, protected: true});
|
||||||
const branches: VersionBranch[] = [];
|
const branches: VersionBranch[] = [];
|
||||||
|
|
||||||
for (const {name} of branchData) {
|
for (const {name} of branchData) {
|
||||||
|
@ -159,7 +156,7 @@ export async function getBranchesForMajorVersions(
|
||||||
|
|
||||||
/** Finds the currently active release trains from the specified version branches. */
|
/** Finds the currently active release trains from the specified version branches. */
|
||||||
export async function findActiveReleaseTrainsFromVersionBranches(
|
export async function findActiveReleaseTrainsFromVersionBranches(
|
||||||
repo: GithubRepo, nextVersion: semver.SemVer, branches: VersionBranch[],
|
repo: GithubRepoWithApi, nextVersion: semver.SemVer, branches: VersionBranch[],
|
||||||
expectedReleaseCandidateMajor: number): Promise<{
|
expectedReleaseCandidateMajor: number): Promise<{
|
||||||
latest: ReleaseTrain | null,
|
latest: ReleaseTrain | null,
|
||||||
releaseCandidate: ReleaseTrain | null,
|
releaseCandidate: ReleaseTrain | null,
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {GithubClient} from '../../../utils/git/github';
|
||||||
import {TargetLabel} from '../config';
|
import {TargetLabel} from '../config';
|
||||||
import {InvalidTargetBranchError, InvalidTargetLabelError} from '../target-label';
|
import {InvalidTargetBranchError, InvalidTargetLabelError} from '../target-label';
|
||||||
|
|
||||||
import {fetchActiveReleaseTrainBranches, getVersionOfBranch, GithubRepo, isReleaseTrainBranch, nextBranchName} from './branches';
|
import {fetchActiveReleaseTrainBranches, getVersionOfBranch, GithubRepoWithApi, isReleaseTrainBranch, nextBranchName} from './branches';
|
||||||
import {assertActiveLtsBranch} from './lts-branch';
|
import {assertActiveLtsBranch} from './lts-branch';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ import {assertActiveLtsBranch} from './lts-branch';
|
||||||
*/
|
*/
|
||||||
export async function getDefaultTargetLabelConfiguration(
|
export async function getDefaultTargetLabelConfiguration(
|
||||||
api: GithubClient, github: GithubConfig, npmPackageName: string): Promise<TargetLabel[]> {
|
api: GithubClient, github: GithubConfig, npmPackageName: string): Promise<TargetLabel[]> {
|
||||||
const repo: GithubRepo = {owner: github.owner, repo: github.name, api};
|
const repo: GithubRepoWithApi = {owner: github.owner, name: github.name, api};
|
||||||
const nextVersion = await getVersionOfBranch(repo, nextBranchName);
|
const nextVersion = await getVersionOfBranch(repo, nextBranchName);
|
||||||
const hasNextMajorTrain = nextVersion.minor === 0;
|
const hasNextMajorTrain = nextVersion.minor === 0;
|
||||||
const {latest, releaseCandidate} = await fetchActiveReleaseTrainBranches(repo, nextVersion);
|
const {latest, releaseCandidate} = await fetchActiveReleaseTrainBranches(repo, nextVersion);
|
||||||
|
|
|
@ -12,7 +12,7 @@ import * as semver from 'semver';
|
||||||
import {promptConfirm, red, warn, yellow} from '../../../utils/console';
|
import {promptConfirm, red, warn, yellow} from '../../../utils/console';
|
||||||
import {InvalidTargetBranchError} from '../target-label';
|
import {InvalidTargetBranchError} from '../target-label';
|
||||||
|
|
||||||
import {getVersionOfBranch, GithubRepo} from './branches';
|
import {getVersionOfBranch, GithubRepoWithApi} from './branches';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of months a major version in Angular is actively supported. See:
|
* Number of months a major version in Angular is actively supported. See:
|
||||||
|
@ -39,7 +39,7 @@ const majorActiveTermSupportDuration = 12;
|
||||||
* @param branchName Branch that is checked to be an active LTS version-branch.
|
* @param branchName Branch that is checked to be an active LTS version-branch.
|
||||||
* */
|
* */
|
||||||
export async function assertActiveLtsBranch(
|
export async function assertActiveLtsBranch(
|
||||||
repo: GithubRepo, representativeNpmPackage: string, branchName: string) {
|
repo: GithubRepoWithApi, representativeNpmPackage: string, branchName: string) {
|
||||||
const version = await getVersionOfBranch(repo, branchName);
|
const version = await getVersionOfBranch(repo, branchName);
|
||||||
const {'dist-tags': distTags, time} =
|
const {'dist-tags': distTags, time} =
|
||||||
await (await fetch(`https://registry.npmjs.org/${representativeNpmPackage}`)).json();
|
await (await fetch(`https://registry.npmjs.org/${representativeNpmPackage}`)).json();
|
||||||
|
|
|
@ -11,6 +11,14 @@ import * as Octokit from '@octokit/rest';
|
||||||
import {RequestParameters} from '@octokit/types';
|
import {RequestParameters} from '@octokit/types';
|
||||||
import {query, types} from 'typed-graphqlify';
|
import {query, types} from 'typed-graphqlify';
|
||||||
|
|
||||||
|
/** Interface describing a Github repository. */
|
||||||
|
export interface GithubRepo {
|
||||||
|
/** Owner login of the repository. */
|
||||||
|
owner: string;
|
||||||
|
/** Name of the repository. */
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
/** Error for failed Github API requests. */
|
/** Error for failed Github API requests. */
|
||||||
export class GithubApiRequestError extends Error {
|
export class GithubApiRequestError extends Error {
|
||||||
constructor(public status: number, message: string) {
|
constructor(public status: number, message: string) {
|
||||||
|
|
Loading…
Reference in New Issue