From 3032a4ab97a9bb3fe204eeecd61b5abcc14885d3 Mon Sep 17 00:00:00 2001 From: AndrewKahr <22359829+AndrewKahr@users.noreply.github.com> Date: Tue, 28 Mar 2023 01:05:31 -0700 Subject: [PATCH] V3 Updates (#529) - Add missing unityLicenseServer input (Fix #480) - Use HEAD when calculating semantic version number. This is a riskier change as this has always used `github.sha` on the runner. However, when pulling in other repos and running the action, it may not be referencing the correct commit on the repo. After testing, though, nothing appears to be broken so this in theory should work fine. (Fix #417) - Setup private token rewrites on Windows images (Fix #428) - Allow setting a custom workspace path within docker container with `dockerWorkspacePath`. (Fix #433) - [Breaking Change] Remove `androidAppBundle` parameter in favor of `androidExportType`. --- .github/pull_request_template.md | 2 + action.yml | 16 +++-- dist/index.js | Bin 19458761 -> 19458211 bytes dist/index.js.map | Bin 13757420 -> 13756742 bytes dist/platforms/ubuntu/steps/build.sh | 1 + .../ubuntu/steps/set_gitcredential.sh | 2 +- dist/platforms/windows/entrypoint.ps1 | 9 ++- dist/platforms/windows/set_gitcredential.ps1 | 20 ++++++ src/model/build-parameters.ts | 3 + src/model/docker.ts | 16 ++--- src/model/input.test.ts | 62 +----------------- src/model/input.ts | 25 ++----- src/model/versioning.ts | 12 +--- 13 files changed, 60 insertions(+), 108 deletions(-) create mode 100644 dist/platforms/windows/set_gitcredential.ps1 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7ae530d3..d7aa5408 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,5 +8,7 @@ - [x] Read the contribution [guide](https://github.com/game-ci/unity-builder/blob/main/CONTRIBUTING.md) and accept the [code](https://github.com/game-ci/unity-builder/blob/main/CODE_OF_CONDUCT.md) of conduct +- [ ] Docs (If new inputs or outputs have been added or changes to behavior that should be documented. Please make + a PR in the [documentation repo](https://github.com/game-ci/documentation)) - [ ] Readme (updated or not needed) - [ ] Tests (added, updated or not needed) diff --git a/action.yml b/action.yml index ca447fae..e605f55a 100644 --- a/action.yml +++ b/action.yml @@ -47,13 +47,9 @@ inputs: required: false default: '' description: 'The android versionCode' - androidAppBundle: - required: false - default: 'false' - description: '[Deprecated] Use androidExportType instead. Whether to build .aab instead of .apk' androidExportType: required: false - default: '' + default: 'androidPackage' description: 'The android export type. Should be androidPackage for apk, androidAppBundle for aab, or androidStudioProject for an android studio project.' @@ -207,6 +203,16 @@ inputs: description: 'The version of Unity Hub to install on MacOS (e.g. 3.4.0). Defaults to latest available on brew if empty string or nothing is specified.' + unityLicensingServer: + default: '' + required: false + description: 'The Unity licensing server address to use for activating Unity.' + dockerWorkspacePath: + default: '/github/workspace' + required: false + description: + 'The path to mount the workspace inside the docker container. For windows, leave out the drive letter. For example + c:/github/workspace should be defined as /github/workspace' outputs: volume: diff --git a/dist/index.js b/dist/index.js index a965daa8cbcb2eef052aabf42e1965d3a1292dd5..5c682c647f270f5751f9143e24541bc646de7646 100644 GIT binary patch delta 1728 zcmZ|Pc~n$Y9Ki82%zZNsvN{W^IOyo$0$8>>EmCS~3T|bKrfiC0LV%fw8CsEBW}{s# z(UMYWQ7iMcn4mV5S>_VhV!4#IC+*o{eSaPQ(F5=%&QO7)CVjGGwTD^P{`fu z{QG6EInAQN!aTlNt(-GkS6fwMTWiVTYNBqjsYo4Csv*Ah6Z%%_BjGAhXWLYa9vY!s zW|N^(t*y_ZnI%C-J5+jGzsWp#dXqzqZEFKVRl8dqMIUo0r`gE*Qk`C_;({g3c0Ff} ziZi#aR<*WZ;}#Wl?laJ_W!VY()G`&*D)a|uUVO9G%MZjbi7UPjWz7L z)MwcA&UB;L_-q5uE3SJ z3Rj~avTzNqMSl#yKwO7G7>psf9z!t<*~r0gjKD~Y!f4!p8!-kq;bz=|TQL^na2v*B z0&68e#7th1E=vP{=(n*2WRl_!ki4t5=g=%R*8}r5}U*> zX(w?=!X@n`5t2wrlq6abBZ-xCkT@kSiCf~4#7W{M36exfk|bHuQIaC*B=Jg8C7mT* TBtA)3NjHh#(!guNQn~FvQe|pi delta 1984 zcmZwH2Xs?a9DwnY=A|Vmqa|(AHU)1P4V6k2Tr>;|Eutcz3@7R%d8DCDQj!-+K^dZ= zGE1!2!II)$I4};DC@L;M1%;|m_ZHl!fZsi0#ohoEfy^$C9^aTG^^s{OY0)h>R7GrGh~ZZ+j#tPGO203Ehkt% zY}0hBjN7##$6u7&?b`YiEOXWbxy`2KIelfv4`4~v@{?oJwfctk<+Zhg;$eS{(W6*Q zbI685Yfgq9_D3T@f9s{?(|6k~?))Rml~ZaXQFC;Cts#Qpm}%&KPomSrJh@<{mLU%= z(bDX#8)d;tZLnOoTuYN%muN0oP$BGcX1|8E>=a}BIK+{MFTz2>`2XPkQeUd&N^Pl@ znd0%v!UIvKrtX;7v&kh_xC0JNjUe?|^RgGa>~e3TmOA6usl`CyId;t>%32pk>b`0{ zV0gT(W0aPP%CKLI9#Jvk=(RC1Lzq>;*uO)Ix+)_qjy+fevtlA@gd&p-|51D8{)CpB zOB4apc#yW z^%~)e#KWeVz%7^cv{kqH?{>1KsL`3&=T4hbTw+5i)ay2|!+~_PMLV=d2V@`<9pOY4 zvXKK9a*>C8xKV&k=!}yfP>3$*if-tRB6!dP#W)!~QG!#@3#B*}r=d6c;B=gUGjSHq zMqiY{i+<>j0T_sLP>w+uj0#j@2+qY&oQLyq0fym1495tJ#6`Fmqc9p{Fcz2KQe1}1 zaRsi#I9!FRaSe2ghYx-jn1BGP5X3}OqXr>_5kV~`A&MAG#4#Cln1Xst#WY-t>o6TN zFcY(IJ!azu+=!bn2RGvu+={uFhxu55g;<0JEJgyip%J%3;tt%2yKpy_U@4YiIac5v ztV9!5;a=Q_`|$uC#6x%(kKj=}hR3lQPvA*Bg{QFw&mf6s@f@DV3s{SFSdR_Zh!?R5 zFX3fu#w&OguVD*b#~XMPZ{clh#WrlmJ9roGVFz~NeSCmj*o|g!3w_Fyks@CiP} zXZRdn;7fdkukj7O#dr7~Kj25~!+!jPpYaQR#c%i>f8YTA#9#Ou2XP38=N6Y(7D6RO z#j2vI*i=$g(p1{0*i{@V=_+ki+Nrcx>7bIKlBv>B#i^2|lC6@X;!?>~$y3Q!ajO)l ibW-W8a*~QrDOBmA(p9CKN_Uka6^~^De-oCeYySaOON-3_ diff --git a/dist/index.js.map b/dist/index.js.map index 1fe06b3b519ad6d1dc997988f6792ceed41f3849..bac9601797709bd929a0678bfeb31c265da53439 100644 GIT binary patch delta 1448 zcmZ|MSy0VU9Ki9ps#{7)b&IS2-@U|DQ9_n%B`FFwAv?FaDy7X$mJlIaNtTX%-=jtH zw`MO(gcoCY$czUMjA6Wa@imqiGxwgE&%-(AcYeR${LZJ>E$Zf1E$TY6y3*(*c2szM z5k_BkH*xf<+ua78%T5t{;Ul!P`+ZJ@twZ zdESosBJzW$TSMF00QX-HRLe^BMYVKwktR2*K!w{s=)R1|SRr zF$jYZjv*L|VHl1GjKD~Y!f1>^B%&}D(HMsqj7KcuFaZ-0j|5D@WK4k(iI|EcOv7}{ zKr&`x7G`4(=3*Y^V*wVzgcPJA4Q4DtIx>)n#mGW7mLLbY$U{B~uoM;)Vi}6C94oLA zt5A&9ScA1F!8)u*DK=muHlYlgu?1UU#Ws{!*QIzNu0uIoWWU~!+BKW0xqHkwWvcqE};RJ(TFQha23~Z9XD_jx6p*!xP!a6 fhx>SdhiFC%9^o;b;3-=14A0Sq7mD@$OOxwQ^jpSP delta 1932 zcmZwFYfw~W7zgm#cG>0b$^x+~=lCiWP{xwC3?*BYA|TlmH4`rf_P`$9o4W@=MbR`d zEnzcwGE<2Z{-t(US^Pbs@ zU-oKme$%UM7qz?fELv5wyFcrv=H$2-vfhdbhFTrw$YZkKIx$pJ{(*$4;i8U9*h7t( zcrN>vdWzrLAMQG@Bupn}(5$AxAN4WH@~i3!RmY~&C93f1s)D$daN)Tbb30tL|Ej*` zx2D~xo#A3vzq-+H{XINHuB2a2H}dpmS}`t3({a9D8-eHl4W5yrnxbslAN#kO;%2P%hHu0B4{-4s)F&tc^R$8I+PI*gxB7QoKHJWaAhMr5XvRwE~e`NF0MJijWU$y44WXFube;0 z9iljk$1|(SWpjubnQT3^e8n3R(*>8!>y~UoOHA^S#UDs9{kM=;<8gcClC>U@NiLr( z3bu6W-)l^yu9`8C^j9&jZ!Y3>@k9I5Gg)md^?z?PP-8JanXHApj-&$KL>YB~qzK8y z7EU77FR6*qL+{Ncp@>h3{XZ!^ll+%VhIpxhWr#!h6r5!;(T#;B9ktgrY1NpCf`h4J zsMU(rU?Hy^ewdkTSTCLBP&?*X!f=_*EYD?QCB<`!OTDG8P%Ctyy}&0j*)I8TYD~iHO5kQkk_fP zn>Md78A#v5$0>#jd{=U0XzDDVU7+BV)I=K9!|RnlzvX8~#IU(;S zX95#&KAAa%wX95JHc=MJ?V@c04&|$I$daovbb0|ln@y4>w@Ywf>?)TWo@hKR>f;?z zcjA_kWfzx3*4hSb{XicNV}Zdq7!PT1AKVWQKssbVCOila!3201vcL@4@CZzVNiZ3v zz*Kk?rom&71Jhv!>$BPSOpGnf(zW>fz{vzAIMMzYoHox zU@feJ^-v2NU?bGQCfE!wz!umFFTyschwbnZ?0}u{GQ0x2paB}e53j;*cnzAM83dvL4nh7 x20nlf;VgUv=b#JDLl7=NH}t^Aa1nap6SxGI;R<{TpTXzw1zc4I`mPDl{{W~~y5Rr- diff --git a/dist/platforms/ubuntu/steps/build.sh b/dist/platforms/ubuntu/steps/build.sh index 66149409..74388fc4 100755 --- a/dist/platforms/ubuntu/steps/build.sh +++ b/dist/platforms/ubuntu/steps/build.sh @@ -153,6 +153,7 @@ fi # Make a given user owner of all artifacts if [[ -n "$CHOWN_FILES_TO" ]]; then + echo "Changing ownership of files to $CHOWN_FILES_TO for $BUILD_PATH_FULL and $UNITY_PROJECT_PATH" chown -R "$CHOWN_FILES_TO" "$BUILD_PATH_FULL" chown -R "$CHOWN_FILES_TO" "$UNITY_PROJECT_PATH" fi diff --git a/dist/platforms/ubuntu/steps/set_gitcredential.sh b/dist/platforms/ubuntu/steps/set_gitcredential.sh index d572a583..a336fc2b 100755 --- a/dist/platforms/ubuntu/steps/set_gitcredential.sh +++ b/dist/platforms/ubuntu/steps/set_gitcredential.sh @@ -9,8 +9,8 @@ else git config --global credential.helper store git config --global --replace-all url."https://token:$GIT_PRIVATE_TOKEN@github.com/".insteadOf ssh://git@github.com/ git config --global --add url."https://token:$GIT_PRIVATE_TOKEN@github.com/".insteadOf git@github.com - git config --global --add url."https://token:$GIT_PRIVATE_TOKEN@github.com/".insteadOf "https://github.com/" + git config --global url."https://ssh:$GIT_PRIVATE_TOKEN@github.com/".insteadOf "ssh://git@github.com/" git config --global url."https://git:$GIT_PRIVATE_TOKEN@github.com/".insteadOf "git@github.com:" diff --git a/dist/platforms/windows/entrypoint.ps1 b/dist/platforms/windows/entrypoint.ps1 index b5255d11..f0a6b555 100644 --- a/dist/platforms/windows/entrypoint.ps1 +++ b/dist/platforms/windows/entrypoint.ps1 @@ -1,6 +1,3 @@ -# Activate Unity -& "c:\steps\activate.ps1" - # Import any necessary registry keys, ie: location of windows 10 sdk # No guarantee that there will be any necessary registry keys, ie: tvOS Get-ChildItem -Path c:\regkeys -File | Foreach {reg import $_.fullname} @@ -8,6 +5,12 @@ Get-ChildItem -Path c:\regkeys -File | Foreach {reg import $_.fullname} # Register the Visual Studio installation so Unity can find it regsvr32 C:\ProgramData\Microsoft\VisualStudio\Setup\x64\Microsoft.VisualStudio.Setup.Configuration.Native.dll +# Setup Git Credentials +& "c:\steps\set_gitcredential.ps1" + +# Activate Unity +& "c:\steps\activate.ps1" + # Build the project & "c:\steps\build.ps1" diff --git a/dist/platforms/windows/set_gitcredential.ps1 b/dist/platforms/windows/set_gitcredential.ps1 new file mode 100644 index 00000000..afb947c6 --- /dev/null +++ b/dist/platforms/windows/set_gitcredential.ps1 @@ -0,0 +1,20 @@ +if ([string]::IsNullOrEmpty($env:GIT_PRIVATE_TOKEN)) { + Write-Host "GIT_PRIVATE_TOKEN unset skipping" +} +else { + Write-Host "GIT_PRIVATE_TOKEN is set configuring git credentials" + + git config --global credential.helper store + git config --global --replace-all "url.https://token:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "ssh://git@github.com/" + git config --global --add "url.https://token:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "git@github.com" + git config --global --add "url.https://token:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "https://github.com/" + + git config --global "url.https://ssh:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "ssh://git@github.com/" + git config --global "url.https://git:$env:GIT_PRIVATE_TOKEN@github.com/".insteadOf "git@github.com:" +} + +Write-Host "---------- git config --list -------------" +git config --list + +Write-Host "---------- git config --list --show-origin -------------" +git config --list --show-origin diff --git a/src/model/build-parameters.ts b/src/model/build-parameters.ts index 03f7378b..8b813ee3 100644 --- a/src/model/build-parameters.ts +++ b/src/model/build-parameters.ts @@ -82,6 +82,8 @@ class BuildParameters { public skipCache!: boolean; public cacheUnityInstallationOnMac!: boolean; public unityHubVersionOnMac!: string; + public dockerWorkspacePath!: string; + public static shouldUseRetainedWorkspaceMode(buildParameters: BuildParameters) { return buildParameters.maxRetainedWorkspaces > 0 && CloudRunner.lockedWorkspace !== ``; } @@ -187,6 +189,7 @@ class BuildParameters { skipCache: CloudRunnerOptions.skipCache, cacheUnityInstallationOnMac: Input.cacheUnityInstallationOnMac, unityHubVersionOnMac: Input.unityHubVersionOnMac, + dockerWorkspacePath: Input.dockerWorkspacePath, }; } diff --git a/src/model/docker.ts b/src/model/docker.ts index 9b438a0f..6e2fa90b 100644 --- a/src/model/docker.ts +++ b/src/model/docker.ts @@ -40,7 +40,7 @@ class Docker { additionalVariables: StringKeyValuePair[] = [], entrypointBash: boolean = false, ): string { - const { workspace, actionFolder, runnerTempPath, sshAgent, gitPrivateToken } = parameters; + const { workspace, actionFolder, runnerTempPath, sshAgent, gitPrivateToken, dockerWorkspacePath } = parameters; const githubHome = path.join(runnerTempPath, '_github_home'); if (!existsSync(githubHome)) mkdirSync(githubHome); @@ -49,16 +49,16 @@ class Docker { const commandPrefix = image === `alpine` ? `/bin/sh` : `/bin/bash`; return `docker run \ - --workdir /github/workspace \ + --workdir ${dockerWorkspacePath} \ --rm \ ${ImageEnvironmentFactory.getEnvVarString(parameters, additionalVariables)} \ --env UNITY_SERIAL \ - --env GITHUB_WORKSPACE=/github/workspace \ + --env GITHUB_WORKSPACE=${dockerWorkspacePath} \ ${gitPrivateToken ? `--env GIT_PRIVATE_TOKEN="${gitPrivateToken}"` : ''} \ ${sshAgent ? '--env SSH_AUTH_SOCK=/ssh-agent' : ''} \ --volume "${githubHome}":"/root:z" \ --volume "${githubWorkflow}":"/github/workflow:z" \ - --volume "${workspace}":"/github/workspace:z" \ + --volume "${workspace}":"${dockerWorkspacePath}:z" \ --volume "${actionFolder}/default-build-script:/UnityBuilderAction:z" \ --volume "${actionFolder}/platforms/ubuntu/steps:/steps:z" \ --volume "${actionFolder}/platforms/ubuntu/entrypoint.sh:/entrypoint.sh:z" \ @@ -72,16 +72,16 @@ class Docker { } static getWindowsCommand(image: string, parameters: DockerParameters): string { - const { workspace, actionFolder, unitySerial, gitPrivateToken } = parameters; + const { workspace, actionFolder, unitySerial, gitPrivateToken, dockerWorkspacePath } = parameters; return `docker run \ - --workdir c:/github/workspace \ + --workdir c:${dockerWorkspacePath} \ --rm \ ${ImageEnvironmentFactory.getEnvVarString(parameters)} \ --env UNITY_SERIAL="${unitySerial}" \ - --env GITHUB_WORKSPACE=c:/github/workspace \ + --env GITHUB_WORKSPACE=c:${dockerWorkspacePath} \ ${gitPrivateToken ? `--env GIT_PRIVATE_TOKEN="${gitPrivateToken}"` : ''} \ - --volume "${workspace}":"c:/github/workspace" \ + --volume "${workspace}":"c:${dockerWorkspacePath}" \ --volume "c:/regkeys":"c:/regkeys" \ --volume "C:/Program Files (x86)/Microsoft Visual Studio":"C:/Program Files (x86)/Microsoft Visual Studio" \ --volume "C:/Program Files (x86)/Windows Kits":"C:/Program Files (x86)/Windows Kits" \ diff --git a/src/model/input.test.ts b/src/model/input.test.ts index 32275812..f5d08d5c 100644 --- a/src/model/input.test.ts +++ b/src/model/input.test.ts @@ -143,81 +143,21 @@ describe('Input', () => { }); }); - describe('androidAppBundle', () => { - it('returns the default value', () => { - expect(Input.androidAppBundle).toStrictEqual(false); - }); - - it('returns true when string true is passed', () => { - const spy = jest.spyOn(core, 'getInput').mockReturnValue('true'); - expect(Input.androidAppBundle).toStrictEqual(true); - expect(spy).toHaveBeenCalledTimes(1); - }); - - it('returns false when string false is passed', () => { - const spy = jest.spyOn(core, 'getInput').mockReturnValue('false'); - expect(Input.androidAppBundle).toStrictEqual(false); - expect(spy).toHaveBeenCalledTimes(1); - }); - }); - describe('androidExportType', () => { it('returns the default value', () => { expect(Input.androidExportType).toStrictEqual('androidPackage'); }); - // TODO: Remove "and androidAppBundle is not set" in v3 test.each` input | expected ${'androidPackage'} | ${'androidPackage'} ${'androidAppBundle'} | ${'androidAppBundle'} ${'androidStudioProject'} | ${'androidStudioProject'} - `('returns $expected when $input is passed and androidAppBundle is not set', ({ input, expected }) => { + `('returns $expected when $input is passed', ({ input, expected }) => { const spy = jest.spyOn(core, 'getInput').mockReturnValue(input); expect(Input.androidExportType).toStrictEqual(expected); expect(spy).toHaveBeenCalledTimes(1); }); - - // TODO: Remove in v3 - test.each` - input | expected - ${'androidPackage'} | ${'androidPackage'} - ${'androidAppBundle'} | ${'androidAppBundle'} - ${'androidStudioProject'} | ${'androidStudioProject'} - `('returns $expected when $input is passed and overrides androidAppBundle if it is set', ({ input, expected }) => { - const spy = jest.spyOn(Input, 'getInput'); - spy.mockImplementationOnce(() => { - return input; - }); - - spy.mockImplementationOnce(() => { - return 'true'; - }); - expect(Input.androidExportType).toStrictEqual(expected); - expect(spy).toHaveBeenCalledTimes(1); - }); - - // TODO: Remove in v3 - test.each` - input | expected - ${'true'} | ${'androidAppBundle'} - ${'false'} | ${'androidPackage'} - `( - 'returns $expected when androidExportType is undefined and androidAppBundle is set to $input', - ({ input, expected }) => { - const spy = jest.spyOn(Input, 'getInput'); - spy.mockImplementationOnce(() => { - return ''; - }); - - spy.mockImplementationOnce(() => { - return input; - }); - - expect(Input.androidExportType).toStrictEqual(expected); - expect(spy).toHaveBeenCalledTimes(2); - }, - ); }); describe('androidSymbolType', () => { diff --git a/src/model/input.ts b/src/model/input.ts index 45f39c76..a4b17657 100644 --- a/src/model/input.ts +++ b/src/model/input.ts @@ -142,27 +142,8 @@ class Input { return Input.getInput('androidVersionCode') || ''; } - static get androidAppBundle(): boolean { - core.warning('androidAppBundle is deprecated, please use androidExportType instead'); - const input = Input.getInput('androidAppBundle') || false; - - return input === 'true'; - } - static get androidExportType(): string { - // TODO: remove this in V3 - const exportType = Input.getInput('androidExportType') || ''; - - if (exportType !== '') { - return exportType; - } - - return Input.androidAppBundle ? 'androidAppBundle' : 'androidPackage'; - - // End TODO - - // Use this in V3 when androidAppBundle is removed - // return Input.getInput('androidExportType') || 'androidPackage'; + return Input.getInput('androidExportType') || 'androidPackage'; } static get androidKeystoreName(): string { @@ -231,6 +212,10 @@ class Input { return Input.getInput('UNITY_LICENSE'); } + static get dockerWorkspacePath(): string { + return Input.getInput('dockerWorkspacePath') || '/github/workspace'; + } + public static ToEnvVarFormat(input: string) { if (input.toUpperCase() === input) { return input; diff --git a/src/model/versioning.ts b/src/model/versioning.ts index bf9e6292..38176907 100644 --- a/src/model/versioning.ts +++ b/src/model/versioning.ts @@ -34,13 +34,6 @@ export default class Versioning { return process.env.GITHUB_REF; } - /** - * The commit SHA that triggered the workflow run. - */ - static get sha() { - return process.env.GITHUB_SHA; - } - /** * Maximum number of lines to print when logging the git diff */ @@ -214,7 +207,7 @@ export default class Versioning { * identifies the current commit. */ static async getVersionDescription() { - return this.git(['describe', '--long', '--tags', '--always', this.sha!]); + return this.git(['describe', '--long', '--tags', '--always', 'HEAD']); } /** @@ -259,10 +252,9 @@ export default class Versioning { /** * Get the total number of commits on head. * - * Note: HEAD should not be used, as it may be detached, resulting in an additional count. */ static async getTotalNumberOfCommits() { - const numberOfCommitsAsString = await this.git(['rev-list', '--count', this.sha!]); + const numberOfCommitsAsString = await this.git(['rev-list', '--count', 'HEAD']); return Number.parseInt(numberOfCommitsAsString, 10); }