From 57c1c889f7b48d04fd94be8d3925dde5cf667ab5 Mon Sep 17 00:00:00 2001 From: Jack Bates Date: Tue, 26 Jan 2021 15:09:28 -0700 Subject: [PATCH] Specify closed PRs to run.ts --- src/queries/all-open-prs-query.ts | 17 ++-- src/queries/projectboard-cards.ts | 38 ++++----- src/queries/schema/GetAllOpenPRs.ts | 60 +++++++++++++++ src/queries/schema/GetAllOpenPRsAndCardIDs.ts | 77 ------------------- src/queries/schema/GetProjectBoardCards.ts | 18 +++++ src/run.ts | 23 +++--- src/util/util.ts | 5 +- 7 files changed, 112 insertions(+), 126 deletions(-) create mode 100644 src/queries/schema/GetAllOpenPRs.ts delete mode 100644 src/queries/schema/GetAllOpenPRsAndCardIDs.ts diff --git a/src/queries/all-open-prs-query.ts b/src/queries/all-open-prs-query.ts index 49135b0a6..14ca7320d 100644 --- a/src/queries/all-open-prs-query.ts +++ b/src/queries/all-open-prs-query.ts @@ -1,16 +1,15 @@ import { gql, TypedDocumentNode } from "@apollo/client/core"; import { client } from "../graphql-client"; -import { GetAllOpenPRsAndCardIDs, GetAllOpenPRsAndCardIDsVariables } from "./schema/GetAllOpenPRsAndCardIDs"; +import { GetAllOpenPRs, GetAllOpenPRsVariables } from "./schema/GetAllOpenPRs"; import { noNullish } from "../util/util"; -export const getAllOpenPRsAndCardIDsQuery: TypedDocumentNode = gql` -query GetAllOpenPRsAndCardIDs($endCursor: String) { +export const getAllOpenPRsQuery: TypedDocumentNode = gql` +query GetAllOpenPRs($endCursor: String) { repository(owner: "DefinitelyTyped", name: "DefinitelyTyped") { id pullRequests(states: OPEN, orderBy: { field: UPDATED_AT, direction: DESC }, first: 100, after: $endCursor) { nodes { number - projectCards(first: 100) { nodes { id } } } pageInfo { hasNextPage @@ -20,22 +19,18 @@ query GetAllOpenPRsAndCardIDs($endCursor: String) { } }`; -export async function getAllOpenPRsAndCardIDs() { +export async function getAllOpenPRs() { const prNumbers: number[] = []; - const cardIDs: string[] = []; let endCursor: string | undefined | null; while (true) { const result = await client.query({ - query: getAllOpenPRsAndCardIDsQuery, + query: getAllOpenPRsQuery, fetchPolicy: "no-cache", variables: { endCursor } }); prNumbers.push(...noNullish(result.data.repository?.pullRequests.nodes).map(pr => pr.number)); - for (const pr of noNullish(result.data.repository?.pullRequests.nodes)) { - cardIDs.push(...noNullish(pr.projectCards.nodes).map(card => card.id)); - } if (!result.data.repository?.pullRequests.pageInfo.hasNextPage) { - return { prNumbers, cardIDs }; + return prNumbers; } endCursor = result.data.repository.pullRequests.pageInfo.endCursor; } diff --git a/src/queries/projectboard-cards.ts b/src/queries/projectboard-cards.ts index 8abefc339..8a467908a 100644 --- a/src/queries/projectboard-cards.ts +++ b/src/queries/projectboard-cards.ts @@ -1,6 +1,7 @@ import { gql, TypedDocumentNode } from "@apollo/client/core"; import { client } from "../graphql-client"; import { GetProjectBoardCards } from "./schema/GetProjectBoardCards"; +import { noNullish } from "../util/util"; const GetProjectBoardCardsQuery: TypedDocumentNode = gql` query GetProjectBoardCards { @@ -17,6 +18,11 @@ const GetProjectBoardCardsQuery: TypedDocumentNode nodes { id updatedAt + content { + ... on PullRequest { + number + } + } } } } @@ -25,16 +31,6 @@ const GetProjectBoardCardsQuery: TypedDocumentNode } }`; -interface CardInfo { - id: string; - updatedAt: string; -} -interface ColumnInfo { - name: string; - totalCount: number; - cards: CardInfo[]; -} - export async function getProjectBoardCards() { const results = await client.query({ query: GetProjectBoardCardsQuery, @@ -47,17 +43,13 @@ export async function getProjectBoardCards() { throw new Error("No project found"); } - const columns: ColumnInfo[] = []; - project.columns.nodes?.forEach(col => { - if (!col) return; - const cards: CardInfo[] = []; - col.cards.nodes?.forEach(card => card && cards.push({ id: card.id, updatedAt: card.updatedAt })); - columns.push({ - name: col.name, - totalCount: col.cards.totalCount, - cards - }); - }); - - return columns; + return noNullish(project.columns.nodes).map(column => ({ + name: column.name, + totalCount: column.cards.totalCount, + cards: noNullish(column.cards.nodes).map(card => ({ + id: card.id, + updatedAt: card.updatedAt, + number: card.content && "number" in card.content ? card.content.number : undefined, + })), + })); } diff --git a/src/queries/schema/GetAllOpenPRs.ts b/src/queries/schema/GetAllOpenPRs.ts new file mode 100644 index 000000000..884ffab71 --- /dev/null +++ b/src/queries/schema/GetAllOpenPRs.ts @@ -0,0 +1,60 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: GetAllOpenPRs +// ==================================================== + +export interface GetAllOpenPRs_repository_pullRequests_nodes { + __typename: "PullRequest"; + /** + * Identifies the pull request number. + */ + number: number; +} + +export interface GetAllOpenPRs_repository_pullRequests_pageInfo { + __typename: "PageInfo"; + /** + * When paginating forwards, are there more items? + */ + hasNextPage: boolean; + /** + * When paginating forwards, the cursor to continue. + */ + endCursor: string | null; +} + +export interface GetAllOpenPRs_repository_pullRequests { + __typename: "PullRequestConnection"; + /** + * A list of nodes. + */ + nodes: (GetAllOpenPRs_repository_pullRequests_nodes | null)[] | null; + /** + * Information to aid in pagination. + */ + pageInfo: GetAllOpenPRs_repository_pullRequests_pageInfo; +} + +export interface GetAllOpenPRs_repository { + __typename: "Repository"; + id: string; + /** + * A list of pull requests that have been opened in the repository. + */ + pullRequests: GetAllOpenPRs_repository_pullRequests; +} + +export interface GetAllOpenPRs { + /** + * Lookup a given repository by the owner and repository name. + */ + repository: GetAllOpenPRs_repository | null; +} + +export interface GetAllOpenPRsVariables { + endCursor?: string | null; +} diff --git a/src/queries/schema/GetAllOpenPRsAndCardIDs.ts b/src/queries/schema/GetAllOpenPRsAndCardIDs.ts deleted file mode 100644 index 12306dcc5..000000000 --- a/src/queries/schema/GetAllOpenPRsAndCardIDs.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// @generated -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: GetAllOpenPRsAndCardIDs -// ==================================================== - -export interface GetAllOpenPRsAndCardIDs_repository_pullRequests_nodes_projectCards_nodes { - __typename: "ProjectCard"; - id: string; -} - -export interface GetAllOpenPRsAndCardIDs_repository_pullRequests_nodes_projectCards { - __typename: "ProjectCardConnection"; - /** - * A list of nodes. - */ - nodes: (GetAllOpenPRsAndCardIDs_repository_pullRequests_nodes_projectCards_nodes | null)[] | null; -} - -export interface GetAllOpenPRsAndCardIDs_repository_pullRequests_nodes { - __typename: "PullRequest"; - /** - * Identifies the pull request number. - */ - number: number; - /** - * List of project cards associated with this pull request. - */ - projectCards: GetAllOpenPRsAndCardIDs_repository_pullRequests_nodes_projectCards; -} - -export interface GetAllOpenPRsAndCardIDs_repository_pullRequests_pageInfo { - __typename: "PageInfo"; - /** - * When paginating forwards, are there more items? - */ - hasNextPage: boolean; - /** - * When paginating forwards, the cursor to continue. - */ - endCursor: string | null; -} - -export interface GetAllOpenPRsAndCardIDs_repository_pullRequests { - __typename: "PullRequestConnection"; - /** - * A list of nodes. - */ - nodes: (GetAllOpenPRsAndCardIDs_repository_pullRequests_nodes | null)[] | null; - /** - * Information to aid in pagination. - */ - pageInfo: GetAllOpenPRsAndCardIDs_repository_pullRequests_pageInfo; -} - -export interface GetAllOpenPRsAndCardIDs_repository { - __typename: "Repository"; - id: string; - /** - * A list of pull requests that have been opened in the repository. - */ - pullRequests: GetAllOpenPRsAndCardIDs_repository_pullRequests; -} - -export interface GetAllOpenPRsAndCardIDs { - /** - * Lookup a given repository by the owner and repository name. - */ - repository: GetAllOpenPRsAndCardIDs_repository | null; -} - -export interface GetAllOpenPRsAndCardIDsVariables { - endCursor?: string | null; -} diff --git a/src/queries/schema/GetProjectBoardCards.ts b/src/queries/schema/GetProjectBoardCards.ts index a4ca22109..1c07d0038 100644 --- a/src/queries/schema/GetProjectBoardCards.ts +++ b/src/queries/schema/GetProjectBoardCards.ts @@ -7,6 +7,20 @@ // GraphQL query operation: GetProjectBoardCards // ==================================================== +export interface GetProjectBoardCards_repository_project_columns_nodes_cards_nodes_content_Issue { + __typename: "Issue"; +} + +export interface GetProjectBoardCards_repository_project_columns_nodes_cards_nodes_content_PullRequest { + __typename: "PullRequest"; + /** + * Identifies the pull request number. + */ + number: number; +} + +export type GetProjectBoardCards_repository_project_columns_nodes_cards_nodes_content = GetProjectBoardCards_repository_project_columns_nodes_cards_nodes_content_Issue | GetProjectBoardCards_repository_project_columns_nodes_cards_nodes_content_PullRequest; + export interface GetProjectBoardCards_repository_project_columns_nodes_cards_nodes { __typename: "ProjectCard"; id: string; @@ -14,6 +28,10 @@ export interface GetProjectBoardCards_repository_project_columns_nodes_cards_nod * Identifies the date and time when the object was last updated. */ updatedAt: any; + /** + * The card content item + */ + content: GetProjectBoardCards_repository_project_columns_nodes_cards_nodes_content | null; } export interface GetProjectBoardCards_repository_project_columns_nodes_cards { diff --git a/src/run.ts b/src/run.ts index 1d7ce4506..87b245be4 100755 --- a/src/run.ts +++ b/src/run.ts @@ -3,12 +3,13 @@ import * as schema from "@octokit/graphql-schema/schema"; import * as yargs from "yargs"; import { process as computeActions } from "./compute-pr-actions"; -import { getAllOpenPRsAndCardIDs } from "./queries/all-open-prs-query"; +import { getAllOpenPRs } from "./queries/all-open-prs-query"; import { queryPRInfo, deriveStateForPR } from "./pr-info"; import { executePrActions } from "./execute-pr-actions"; import { getProjectBoardCards } from "./queries/projectboard-cards"; import { runQueryToGetPRForCardId } from "./queries/card-id-to-pr-query"; import { createMutation, client } from "./graphql-client"; +import { flatten } from "./util/util"; import { render } from "prettyjson"; import { inspect } from "util"; @@ -26,21 +27,18 @@ const args = yargs(process.argv.slice(2)) "show-actions": { alias: ["s4"], type: "boolean", desc: "display actions" }, "show-mutations": { alias: ["s5"], type: "boolean", desc: "display mutations" }, }) - .coerce("_", (prs: (number|string)[]) => prs.map(pr => { - if (typeof pr === "number") return (n: number) => n === pr; - if (pr.match(/^\d+$/)) return (n: number) => n === +pr; + .coerce("_", (prs: (number|string)[]) => flatten(prs.map(pr => { + if (typeof pr === "number") return pr; + if (pr.match(/^\d+$/)) return +pr; const m = pr.match(/^(\d+)-(\d+)$/); if (!m) throw new Error(`bad PR or PR range argument: "${pr}"`); const lo = +m[1]!, hi = +m[2]!; - return (n: number) => lo <= n && n <= hi; - })) + return new Array(hi - lo + 1).map((empty, i) => lo + i); + }))) .help("h").alias("h", "help") .strict() .argv; -const shouldRunOn: (n: number) => boolean = - args._.length === 0 ? _n => true : n => args._.some(p => p(n)); - const xform = (x: unknown, xlate: (s: string) => string): unknown => { if (typeof x === "string") return xlate(x); if (typeof x !== "object" || x === null) return x; @@ -62,10 +60,9 @@ const show = (name: string, value: unknown) => { const start = async function () { console.log(`Getting open PRs.`); - const { prNumbers: prs, cardIDs } = await getAllOpenPRsAndCardIDs(); + const prs = args._.length ? args._ : await getAllOpenPRs(); // for (const pr of prs) { - if (!shouldRunOn(pr)) continue; console.log(`Processing #${pr} (${prs.indexOf(pr) + 1} of ${prs.length})...`); // Generate the info for the PR from scratch const info = await queryPRInfo(pr); @@ -90,7 +87,7 @@ const start = async function () { const mutations = await executePrActions(actions, prInfo, args.dry); if (args["show-mutations"] ?? args.dry) show("Mutations", mutations); } - if (args.dry || !args.cleanup) return; + if (args.dry || !args.cleanup || args._.length) return; // console.log("Cleaning up cards"); const columns = await getProjectBoardCards(); @@ -122,7 +119,7 @@ const start = async function () { // Handle other columns for (const column of columns) { if (column.name === "Recently Merged") continue; - const ids = column.cards.map(c => c.id).filter(c => !cardIDs.includes(c)); + const ids = column.cards.filter(c => c.number && !prs.includes(c.number)).map(c => c.id); if (ids.length === 0) continue; console.log(`Cleaning up closed PRs in "${column.name}"`); // don't actually do the deletions, until I follow this and make sure that it's working fine diff --git a/src/util/util.ts b/src/util/util.ts index 900724158..560fbef22 100644 --- a/src/util/util.ts +++ b/src/util/util.ts @@ -5,8 +5,9 @@ export function noNullish(arr: ReadonlyArray | null | u return arr.filter(arr => arr != null) as T[]; } -export function flatten(xs: T[]) { - return ([] as unknown as T).concat(...xs) as T; +export function flatten(xs: T[]) { + type U = T extends (infer U)[] ? U : T; + return ([] as U[]).concat(...xs as U[]); } export function unique(xs: T[]) {