From 6c2dd8e28ddc7a13191ec384c3a43a269d600aa9 Mon Sep 17 00:00:00 2001
From: Sergei Zharinov <zharinov@users.noreply.github.com>
Date: Wed, 7 Sep 2022 15:12:20 +0300
Subject: [PATCH] refactor(github): Extend common `Pr` type to support
 `updatedAt` field (#17671)

---
 .../github/__snapshots__/index.spec.ts.snap   | 90 -------------------
 lib/modules/platform/github/common.ts         |  8 +-
 lib/modules/platform/github/index.spec.ts     | 53 +++++++++--
 lib/modules/platform/github/index.ts          | 16 ++--
 lib/modules/platform/github/pr.ts             |  7 +-
 lib/modules/platform/github/types.ts          | 20 +----
 6 files changed, 65 insertions(+), 129 deletions(-)

diff --git a/lib/modules/platform/github/__snapshots__/index.spec.ts.snap b/lib/modules/platform/github/__snapshots__/index.spec.ts.snap
index 7f398e4800..2289cddf8c 100644
--- a/lib/modules/platform/github/__snapshots__/index.spec.ts.snap
+++ b/lib/modules/platform/github/__snapshots__/index.spec.ts.snap
@@ -1,95 +1,5 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`modules/platform/github/index getBranchPr(branchName) should cache and return the PR object 1`] = `
-{
-  "bodyStruct": {
-    "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
-  },
-  "displayNumber": "Pull Request #91",
-  "number": 91,
-  "sourceBranch": "somebranch",
-  "sourceRepo": "some/repo",
-  "state": "open",
-  "title": "Some title",
-}
-`;
-
-exports[`modules/platform/github/index getBranchPr(branchName) should reopen and cache autoclosed PR 1`] = `
-{
-  "bodyStruct": {
-    "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
-  },
-  "displayNumber": "Pull Request #91",
-  "number": 91,
-  "sourceBranch": "somebranch",
-  "sourceRepo": "some/repo",
-  "state": "open",
-  "title": "old title",
-}
-`;
-
-exports[`modules/platform/github/index getPr(prNo) should return PR 1`] = `
-{
-  "bodyStruct": {
-    "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
-  },
-  "displayNumber": "Pull Request #2500",
-  "number": 2500,
-  "sourceBranch": "renovate/jest-monorepo",
-  "sourceRepo": "some/repo",
-  "state": "open",
-  "title": "chore(deps): update dependency jest to v23.6.0",
-}
-`;
-
-exports[`modules/platform/github/index getPr(prNo) should return a PR object - 0 1`] = `
-{
-  "bodyStruct": {
-    "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
-  },
-  "createdAt": "01-01-2022",
-  "displayNumber": "Pull Request #1234",
-  "hasAssignees": true,
-  "labels": [
-    "foo",
-    "bar",
-  ],
-  "number": 1234,
-  "sha": "def",
-  "sourceBranch": "some/branch",
-  "state": "merged",
-  "title": "Some title",
-}
-`;
-
-exports[`modules/platform/github/index getPr(prNo) should return a PR object - 1 1`] = `
-{
-  "bodyStruct": {
-    "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
-  },
-  "displayNumber": "Pull Request #1234",
-  "hasAssignees": true,
-  "hasReviewers": true,
-  "number": 1234,
-  "sourceBranch": "some/branch",
-  "state": "open",
-  "title": "Some title",
-}
-`;
-
-exports[`modules/platform/github/index getPr(prNo) should return a PR object - 2 1`] = `
-{
-  "bodyStruct": {
-    "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
-  },
-  "displayNumber": "Pull Request #1234",
-  "number": 1234,
-  "sourceBranch": "some/branch",
-  "state": "open",
-  "title": "Some title",
-}
-`;
-
 exports[`modules/platform/github/index getRepoForceRebase should throw 401 1`] = `"Response code 401 (Unauthorized)"`;
 
 exports[`modules/platform/github/index getRepos should return an array of repos 1`] = `
diff --git a/lib/modules/platform/github/common.ts b/lib/modules/platform/github/common.ts
index fa993fca1e..8a039c4629 100644
--- a/lib/modules/platform/github/common.ts
+++ b/lib/modules/platform/github/common.ts
@@ -1,20 +1,19 @@
 import is from '@sindresorhus/is';
 import { PrState } from '../../../types';
 import { getPrBodyStruct } from '../pr-body';
-import type { Pr } from '../types';
-import type { GhRestPr } from './types';
+import type { GhPr, GhRestPr } from './types';
 
 /**
  * @see https://docs.github.com/en/rest/reference/pulls#list-pull-requests
  */
-export function coerceRestPr(pr: GhRestPr | null | undefined): Pr | null {
+export function coerceRestPr(pr: GhRestPr | null | undefined): GhPr | null {
   // istanbul ignore if
   if (!pr) {
     return null;
   }
 
   const bodyStruct = pr.bodyStruct ?? getPrBodyStruct(pr.body);
-  const result: Pr = {
+  const result: GhPr = {
     displayNumber: `Pull Request #${pr.number}`,
     number: pr.number,
     sourceBranch: pr.head?.ref,
@@ -24,6 +23,7 @@ export function coerceRestPr(pr: GhRestPr | null | undefined): Pr | null {
         ? PrState.Merged
         : pr.state,
     bodyStruct,
+    updatedAt: pr.updated_at,
   };
 
   if (pr.head?.sha) {
diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts
index 4f591154a4..07a109f2d3 100644
--- a/lib/modules/platform/github/index.spec.ts
+++ b/lib/modules/platform/github/index.spec.ts
@@ -818,6 +818,7 @@ describe('modules/platform/github/index', () => {
             head: { ref: 'somebranch', repo: { full_name: 'other/repo' } },
             state: PrState.Open,
             title: 'PR from another repo',
+            updated_at: '01-09-2022',
           },
           {
             number: 91,
@@ -825,6 +826,7 @@ describe('modules/platform/github/index', () => {
             head: { ref: 'somebranch', repo: { full_name: 'some/repo' } },
             state: PrState.Open,
             title: 'Some title',
+            updated_at: '01-09-2022',
           },
         ]);
       await github.initRepo({ repository: 'some/repo' });
@@ -832,7 +834,7 @@ describe('modules/platform/github/index', () => {
       const pr = await github.getBranchPr('somebranch');
       const pr2 = await github.getBranchPr('somebranch');
 
-      expect(pr).toMatchSnapshot();
+      expect(pr).toMatchObject({ number: 91, sourceBranch: 'somebranch' });
       expect(pr2).toEqual(pr);
     });
 
@@ -848,6 +850,7 @@ describe('modules/platform/github/index', () => {
             number: 90,
             head: { ref: 'somebranch', repo: { full_name: 'other/repo' } },
             state: PrState.Open,
+            updated_at: '01-09-2022',
           },
           {
             number: 91,
@@ -855,6 +858,7 @@ describe('modules/platform/github/index', () => {
             title: 'old title - autoclosed',
             state: PrState.Closed,
             closed_at: DateTime.now().minus({ days: 6 }).toISO(),
+            updated_at: '01-09-2022',
           },
         ])
         .post('/repos/some/repo/git/refs')
@@ -866,13 +870,14 @@ describe('modules/platform/github/index', () => {
           head: { ref: 'somebranch', repo: { full_name: 'some/repo' } },
           state: PrState.Open,
           title: 'old title',
+          updated_at: '01-09-2022',
         });
       await github.initRepo({ repository: 'some/repo' });
 
       const pr = await github.getBranchPr('somebranch');
       const pr2 = await github.getBranchPr('somebranch');
 
-      expect(pr).toMatchSnapshot({ number: 91 });
+      expect(pr).toMatchObject({ number: 91, sourceBranch: 'somebranch' });
       expect(pr2).toEqual(pr);
     });
 
@@ -2427,6 +2432,7 @@ describe('modules/platform/github/index', () => {
             },
             title: 'build(deps): update dependency delay to v4.0.1',
             state: PrState.Closed,
+            updated_at: '01-09-2022',
           },
           {
             number: 2500,
@@ -2436,12 +2442,22 @@ describe('modules/platform/github/index', () => {
             },
             state: PrState.Open,
             title: 'chore(deps): update dependency jest to v23.6.0',
+            updated_at: '01-09-2022',
           },
         ]);
       await github.initRepo({ repository: 'some/repo' });
       const pr = await github.getPr(2500);
       expect(pr).toBeDefined();
-      expect(pr).toMatchSnapshot();
+      expect(pr).toMatchObject({
+        number: 2500,
+        bodyStruct: { hash: expect.any(String) },
+        displayNumber: 'Pull Request #2500',
+        sourceBranch: 'renovate/jest-monorepo',
+        sourceRepo: 'some/repo',
+        state: 'open',
+        title: 'chore(deps): update dependency jest to v23.6.0',
+        updatedAt: '01-09-2022',
+      });
     });
 
     it('should return closed PR', async () => {
@@ -2529,10 +2545,11 @@ describe('modules/platform/github/index', () => {
           labels: [{ name: 'foo' }, { name: 'bar' }],
           assignee: { login: 'foobar' },
           created_at: '01-01-2022',
+          updated_at: '01-09-2022',
         });
       await github.initRepo({ repository: 'some/repo' });
       const pr = await github.getPr(1234);
-      expect(pr).toMatchSnapshot({ state: 'merged' });
+      expect(pr).toMatchObject({ number: 1234, state: 'merged' });
     });
 
     it(`should return a PR object - 1`, async () => {
@@ -2554,10 +2571,23 @@ describe('modules/platform/github/index', () => {
           title: 'Some title',
           assignees: [{ login: 'foo' }],
           requested_reviewers: [{ login: 'bar' }],
+          updated_at: '01-09-2022',
         });
       await github.initRepo({ repository: 'some/repo' });
       const pr = await github.getPr(1234);
-      expect(pr).toMatchSnapshot();
+      expect(pr).toMatchObject({
+        bodyStruct: {
+          hash: expect.any(String),
+        },
+        displayNumber: 'Pull Request #1234',
+        hasAssignees: true,
+        hasReviewers: true,
+        number: 1234,
+        sourceBranch: 'some/branch',
+        state: 'open',
+        title: 'Some title',
+        updatedAt: '01-09-2022',
+      });
     });
 
     it(`should return a PR object - 2`, async () => {
@@ -2576,10 +2606,21 @@ describe('modules/platform/github/index', () => {
           head: { ref: 'some/branch' },
           commits: 1,
           title: 'Some title',
+          updated_at: '01-09-2022',
         });
       await github.initRepo({ repository: 'some/repo' });
       const pr = await github.getPr(1234);
-      expect(pr).toMatchSnapshot();
+      expect(pr).toMatchObject({
+        bodyStruct: {
+          hash: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
+        },
+        displayNumber: 'Pull Request #1234',
+        number: 1234,
+        sourceBranch: 'some/branch',
+        state: 'open',
+        title: 'Some title',
+        updatedAt: '01-09-2022',
+      });
     });
   });
 
diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts
index db1b1baf49..082fc58b5e 100644
--- a/lib/modules/platform/github/index.ts
+++ b/lib/modules/platform/github/index.ts
@@ -51,7 +51,6 @@ import type {
   PlatformParams,
   PlatformPrOptions,
   PlatformResult,
-  Pr,
   RepoParams,
   RepoResult,
   UpdatePrConfig,
@@ -73,6 +72,7 @@ import type {
   Comment,
   GhAutomergeResponse,
   GhBranchStatus,
+  GhPr,
   GhRepo,
   GhRestPr,
   LocalRepoConfig,
@@ -566,7 +566,7 @@ export async function getRepoForceRebase(): Promise<boolean> {
   return !!config.repoForceRebase;
 }
 
-function cachePr(pr?: Pr | null): void {
+function cachePr(pr?: GhPr | null): void {
   config.prList ??= [];
   if (pr) {
     for (let idx = 0; idx < config.prList.length; idx += 1) {
@@ -581,7 +581,7 @@ function cachePr(pr?: Pr | null): void {
 }
 
 // Fetch fresh Pull Request and cache it when possible
-async function fetchPr(prNo: number): Promise<Pr | null> {
+async function fetchPr(prNo: number): Promise<GhPr | null> {
   try {
     const { body: ghRestPr } = await githubApi.getJson<GhRestPr>(
       `repos/${config.parentRepo ?? config.repository}/pulls/${prNo}`
@@ -596,7 +596,7 @@ async function fetchPr(prNo: number): Promise<Pr | null> {
 }
 
 // Gets details for a PR
-export async function getPr(prNo: number): Promise<Pr | null> {
+export async function getPr(prNo: number): Promise<GhPr | null> {
   if (!prNo) {
     return null;
   }
@@ -619,7 +619,7 @@ function matchesState(state: string, desiredState: string): boolean {
   return state === desiredState;
 }
 
-export async function getPrList(): Promise<Pr[]> {
+export async function getPrList(): Promise<GhPr[]> {
   if (!config.prList) {
     const repo = config.parentRepo ?? config.repository;
     const username =
@@ -640,7 +640,7 @@ export async function findPr({
   branchName,
   prTitle,
   state = PrState.All,
-}: FindPRConfig): Promise<Pr | null> {
+}: FindPRConfig): Promise<GhPr | null> {
   logger.debug(`findPr(${branchName}, ${prTitle}, ${state})`);
   const prList = await getPrList();
   const pr = prList.find((p) => {
@@ -671,7 +671,7 @@ export async function findPr({
 const REOPEN_THRESHOLD_MILLIS = 1000 * 60 * 60 * 24 * 7;
 
 // Returns the Pull Request for a branch. Null if not exists.
-export async function getBranchPr(branchName: string): Promise<Pr | null> {
+export async function getBranchPr(branchName: string): Promise<GhPr | null> {
   logger.debug(`getBranchPr(${branchName})`);
 
   const openPr = await findPr({
@@ -1411,7 +1411,7 @@ export async function createPr({
   labels,
   draftPR = false,
   platformOptions,
-}: CreatePRConfig): Promise<Pr | null> {
+}: CreatePRConfig): Promise<GhPr | null> {
   const body = sanitize(rawBody);
   const base = targetBranch;
   // Include the repository owner to handle forkMode and regular mode
diff --git a/lib/modules/platform/github/pr.ts b/lib/modules/platform/github/pr.ts
index 416afd3a91..76a8bff0db 100644
--- a/lib/modules/platform/github/pr.ts
+++ b/lib/modules/platform/github/pr.ts
@@ -6,10 +6,9 @@ import { getCache } from '../../../util/cache/repository';
 import type { GithubHttp, GithubHttpOptions } from '../../../util/http/github';
 import { parseLinkHeader } from '../../../util/url';
 import { getPrBodyStruct } from '../pr-body';
-import type { Pr } from '../types';
 import { ApiCache } from './api-cache';
 import { coerceRestPr } from './common';
-import type { ApiPageCache, GhRestPr } from './types';
+import type { ApiPageCache, GhPr, GhRestPr } from './types';
 
 function removeUrlFields(input: unknown): void {
   if (is.plainObject(input)) {
@@ -97,8 +96,8 @@ export async function getPrCache(
   http: GithubHttp,
   repo: string,
   username: string | null
-): Promise<Record<number, Pr>> {
-  const prCache: Record<number, Pr> = {};
+): Promise<Record<number, GhPr>> {
+  const prCache: Record<number, GhPr> = {};
   const prApiCache = getPrApiCache();
   const isInitial = is.emptyArray(prApiCache.getItems());
 
diff --git a/lib/modules/platform/github/types.ts b/lib/modules/platform/github/types.ts
index 86fdc330c6..e1d66645fc 100644
--- a/lib/modules/platform/github/types.ts
+++ b/lib/modules/platform/github/types.ts
@@ -53,22 +53,8 @@ export interface GhRestPr {
   _links?: unknown;
 }
 
-export interface GhGraphQlPr {
-  number: number;
-  title: string;
-  body?: string;
-  state?: string;
-  headRefName: string;
-  baseRefName?: string;
-  labels?: { nodes?: { name: string }[] };
-  assignees?: { totalCount: number };
-  reviewRequests?: { totalCount: number };
-  comments?: {
-    nodes?: {
-      databaseId: number;
-      body: string;
-    }[];
-  };
+export interface GhPr extends Pr {
+  updatedAt: string;
 }
 
 export interface UserDetails {
@@ -95,7 +81,7 @@ export interface LocalRepoConfig {
   parentRepo: string | null;
   forkMode?: boolean;
   forkToken?: string;
-  prList: Pr[] | null;
+  prList: GhPr[] | null;
   issueList: any[] | null;
   mergeMethod: 'rebase' | 'squash' | 'merge';
   defaultBranch: string;
-- 
GitLab