diff --git a/packages/api-client/src/schema.ts b/packages/api-client/src/schema.ts index bae7d97..626e287 100644 --- a/packages/api-client/src/schema.ts +++ b/packages/api-client/src/schema.ts @@ -235,6 +235,7 @@ export interface operations { prHeadCommit?: string | null; referenceCommit?: string | null; referenceBranch?: string | null; + parentCommits?: components["schemas"]["Sha1Hash"][] | null; /** @enum {string|null} */ mode?: "ci" | "monitoring" | null; ciProvider?: string | null; diff --git a/packages/core/src/ci-environment/git.ts b/packages/core/src/ci-environment/git.ts index 07c2955..ebaea48 100644 --- a/packages/core/src/ci-environment/git.ts +++ b/packages/core/src/ci-environment/git.ts @@ -69,7 +69,7 @@ export function getMergeBaseCommitSha(input: { base: string; head: string; }): string | null { - let depth = 50; + let depth = 200; while (depth < 1000) { const mergeBase = getMergeBaseCommitShaWithDepth({ depth, @@ -78,7 +78,18 @@ export function getMergeBaseCommitSha(input: { if (mergeBase) { return mergeBase; } - depth += 50; + depth += 200; } return null; } + +export function listParentCommits(input: { sha: string }): string[] | null { + try { + execSync(`git fetch --depth 200 origin ${input.sha}`); + const raw = execSync(`git log --format "%H" -n 200 ${input.sha}`); + const shas = raw.toString().trim().split("\n"); + return shas; + } catch { + return null; + } +} diff --git a/packages/core/src/ci-environment/index.ts b/packages/core/src/ci-environment/index.ts index 23ffaa5..d3b9d24 100644 --- a/packages/core/src/ci-environment/index.ts +++ b/packages/core/src/ci-environment/index.ts @@ -53,6 +53,17 @@ export function getMergeBaseCommitSha(input: { return service.getMergeBaseCommitSha(input, context); } +/** + * Get the merge base commit. + */ +export function listParentCommits(input: { sha: string }): string[] | null { + const context = createContext(); + const service = getCiService(context); + if (!service) { + return null; + } + return service.listParentCommits(input, context); +} /** * Get the CI environment. */ diff --git a/packages/core/src/ci-environment/services/bitrise.ts b/packages/core/src/ci-environment/services/bitrise.ts index 915f43d..eccd02b 100644 --- a/packages/core/src/ci-environment/services/bitrise.ts +++ b/packages/core/src/ci-environment/services/bitrise.ts @@ -1,4 +1,4 @@ -import { getMergeBaseCommitSha } from "../git"; +import { getMergeBaseCommitSha, listParentCommits } from "../git"; import type { Service, Context } from "../types"; const getPrNumber = ({ env }: Context) => { @@ -25,6 +25,7 @@ const service: Service = { }; }, getMergeBaseCommitSha, + listParentCommits, }; export default service; diff --git a/packages/core/src/ci-environment/services/buildkite.ts b/packages/core/src/ci-environment/services/buildkite.ts index ef3f41c..f487328 100644 --- a/packages/core/src/ci-environment/services/buildkite.ts +++ b/packages/core/src/ci-environment/services/buildkite.ts @@ -1,5 +1,5 @@ import type { Service } from "../types"; -import { head, branch, getMergeBaseCommitSha } from "../git"; +import { head, branch, getMergeBaseCommitSha, listParentCommits } from "../git"; const service: Service = { name: "Buildkite", @@ -24,6 +24,7 @@ const service: Service = { }; }, getMergeBaseCommitSha, + listParentCommits, }; export default service; diff --git a/packages/core/src/ci-environment/services/circleci.ts b/packages/core/src/ci-environment/services/circleci.ts index cacc10c..37b8cf4 100644 --- a/packages/core/src/ci-environment/services/circleci.ts +++ b/packages/core/src/ci-environment/services/circleci.ts @@ -1,4 +1,4 @@ -import { getMergeBaseCommitSha } from "../git"; +import { getMergeBaseCommitSha, listParentCommits } from "../git"; import type { Service, Context } from "../types"; const getPrNumber = ({ env }: Context) => { @@ -31,6 +31,7 @@ const service: Service = { }; }, getMergeBaseCommitSha, + listParentCommits, }; export default service; diff --git a/packages/core/src/ci-environment/services/git.ts b/packages/core/src/ci-environment/services/git.ts index 9d5688e..e305f53 100644 --- a/packages/core/src/ci-environment/services/git.ts +++ b/packages/core/src/ci-environment/services/git.ts @@ -4,6 +4,7 @@ import { branch, checkIsGitRepository, getMergeBaseCommitSha, + listParentCommits, } from "../git"; const service: Service = { @@ -26,6 +27,7 @@ const service: Service = { }; }, getMergeBaseCommitSha, + listParentCommits, }; export default service; diff --git a/packages/core/src/ci-environment/services/github-actions.ts b/packages/core/src/ci-environment/services/github-actions.ts index 25c3fd8..3596ec1 100644 --- a/packages/core/src/ci-environment/services/github-actions.ts +++ b/packages/core/src/ci-environment/services/github-actions.ts @@ -2,7 +2,7 @@ import { existsSync, readFileSync } from "node:fs"; import type { Service, Context } from "../types"; import axios from "axios"; import { debug } from "../../debug"; -import { getMergeBaseCommitSha } from "../git"; +import { getMergeBaseCommitSha, listParentCommits } from "../git"; type EventPayload = { pull_request?: { @@ -177,6 +177,7 @@ const service: Service = { }; }, getMergeBaseCommitSha, + listParentCommits, }; export default service; diff --git a/packages/core/src/ci-environment/services/gitlab.ts b/packages/core/src/ci-environment/services/gitlab.ts index 6321798..a06fb4d 100644 --- a/packages/core/src/ci-environment/services/gitlab.ts +++ b/packages/core/src/ci-environment/services/gitlab.ts @@ -1,4 +1,4 @@ -import { getMergeBaseCommitSha } from "../git"; +import { getMergeBaseCommitSha, listParentCommits } from "../git"; import type { Service } from "../types"; const service: Service = { @@ -21,6 +21,7 @@ const service: Service = { }; }, getMergeBaseCommitSha, + listParentCommits, }; export default service; diff --git a/packages/core/src/ci-environment/services/heroku.ts b/packages/core/src/ci-environment/services/heroku.ts index e23f6ad..3b21208 100644 --- a/packages/core/src/ci-environment/services/heroku.ts +++ b/packages/core/src/ci-environment/services/heroku.ts @@ -1,5 +1,5 @@ import type { Service } from "../types"; -import { getMergeBaseCommitSha } from "../git"; +import { getMergeBaseCommitSha, listParentCommits } from "../git"; const service: Service = { name: "Heroku", @@ -19,6 +19,7 @@ const service: Service = { nonce: env.HEROKU_TEST_RUN_ID || null, }), getMergeBaseCommitSha, + listParentCommits, }; export default service; diff --git a/packages/core/src/ci-environment/services/travis.ts b/packages/core/src/ci-environment/services/travis.ts index cc846ad..fe767b3 100644 --- a/packages/core/src/ci-environment/services/travis.ts +++ b/packages/core/src/ci-environment/services/travis.ts @@ -1,5 +1,5 @@ import type { Context, Service } from "../types"; -import { getMergeBaseCommitSha } from "../git"; +import { getMergeBaseCommitSha, listParentCommits } from "../git"; const getOwner = ({ env }: Context) => { if (!env.TRAVIS_REPO_SLUG) return null; @@ -38,6 +38,7 @@ const service: Service = { }; }, getMergeBaseCommitSha, + listParentCommits, }; export default service; diff --git a/packages/core/src/ci-environment/types.ts b/packages/core/src/ci-environment/types.ts index c27bb50..bae67a3 100644 --- a/packages/core/src/ci-environment/types.ts +++ b/packages/core/src/ci-environment/types.ts @@ -87,4 +87,10 @@ export interface Service { }, ctx: Context, ): string | null; + listParentCommits( + input: { + sha: string; + }, + ctx: Context, + ): string[] | null; } diff --git a/packages/core/src/upload.ts b/packages/core/src/upload.ts index b064834..68cb31f 100644 --- a/packages/core/src/upload.ts +++ b/packages/core/src/upload.ts @@ -13,7 +13,7 @@ import { debug, debugTime, debugTimeEnd } from "./debug"; import { chunk } from "./util/chunk"; import { getPlaywrightTracePath, readMetadata } from "@argos-ci/util"; import { getArgosCoreSDKIdentifier } from "./version"; -import { getMergeBaseCommitSha } from "./ci-environment"; +import { getMergeBaseCommitSha, listParentCommits } from "./ci-environment"; /** * Size of the chunks used to upload screenshots to Argos. @@ -213,32 +213,50 @@ export async function upload(params: UploadParameters) { if (projectResponse.error) { throwAPIError(projectResponse.error); } + debug("Project fetched", projectResponse.data); + const { defaultBaseBranch, hasRemoteContentAccess } = projectResponse.data; - const referenceBranch = config.referenceBranch || defaultBaseBranch; + const referenceCommit = (() => { if (config.referenceCommit) { debug("Found reference commit in config", config.referenceCommit); return config.referenceCommit; } + // If we have remote access, we will fetch it from the Git Provider. if (hasRemoteContentAccess) { return null; } - // We use the pull request as base branch if possible. - const base = config.prBaseBranch || referenceBranch; + // We use the pull request as base branch if possible + // else branch specified by the user or the default branch. + const base = + config.referenceBranch || config.prBaseBranch || defaultBaseBranch; const sha = getMergeBaseCommitSha({ base, head: config.branch }); if (sha) { - debug("Found reference commit from git", sha); + debug("Found merge base", sha); } else { - debug("No reference commit found in git"); + debug("No merge base found"); } return sha; })(); + const parentCommits = (() => { + // If we have remote access, we will fetch them from the Git Provider. + if (hasRemoteContentAccess) { + return null; + } + + if (referenceCommit) { + return listParentCommits({ sha: referenceCommit }); + } + + return []; + })(); + // Create build debug("Creating build"); const [pwTraceKeys, screenshotKeys] = screenshots.reduce( @@ -269,8 +287,9 @@ export async function upload(params: UploadParameters) { pwTraceKeys, prNumber: config.prNumber, prHeadCommit: config.prHeadCommit, - referenceBranch, + referenceBranch: config.referenceBranch, referenceCommit, + parentCommits, argosSdk, ciProvider: config.ciProvider, runId: config.runId,