diff options
| author | eric sciple <ericsciple@users.noreply.github.com> | 2020-05-21 11:09:16 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-21 11:09:16 -0400 |
| commit | 31d9f35c90667154e76ccca096898caab3e5bba7 (patch) | |
| tree | 8a0ab6e5fac61e5a978cf617c1696a35db7761ef /src | |
| parent | dc7f67634a8d0479d93b46911e11fb5f75a6baf1 (diff) | |
telemetry for incorrect merge commit (#253)
Diffstat (limited to 'src')
| -rw-r--r-- | src/git-command-manager.ts | 7 | ||||
| -rw-r--r-- | src/git-source-provider.ts | 12 | ||||
| -rw-r--r-- | src/ref-helper.ts | 108 |
3 files changed, 123 insertions, 4 deletions
diff --git a/src/git-command-manager.ts b/src/git-command-manager.ts index 4cbfe4a..495075a 100644 --- a/src/git-command-manager.ts +++ b/src/git-command-manager.ts @@ -29,7 +29,7 @@ export interface IGitCommandManager { isDetached(): Promise<boolean> lfsFetch(ref: string): Promise<void> lfsInstall(): Promise<void> - log1(): Promise<void> + log1(): Promise<string> remoteAdd(remoteName: string, remoteUrl: string): Promise<void> removeEnvironmentVariable(name: string): void setEnvironmentVariable(name: string, value: string): void @@ -225,8 +225,9 @@ class GitCommandManager { await this.execGit(['lfs', 'install', '--local']) } - async log1(): Promise<void> { - await this.execGit(['log', '-1']) + async log1(): Promise<string> { + const output = await this.execGit(['log', '-1']) + return output.stdout } async remoteAdd(remoteName: string, remoteUrl: string): Promise<void> { diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index 6855288..bde53bb 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -170,7 +170,17 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> { } // Dump some info about the checked out commit - await git.log1() + const commitInfo = await git.log1() + + // Check for incorrect pull request merge commit + await refHelper.checkCommitInfo( + settings.authToken, + commitInfo, + settings.repositoryOwner, + settings.repositoryName, + settings.ref, + settings.commit + ) } finally { // Remove auth if (!settings.persistCredentials) { diff --git a/src/ref-helper.ts b/src/ref-helper.ts index ff256af..f600179 100644 --- a/src/ref-helper.ts +++ b/src/ref-helper.ts @@ -1,4 +1,7 @@ +import {URL} from 'url' import {IGitCommandManager} from './git-command-manager' +import * as core from '@actions/core' +import * as github from '@actions/github' export interface ICheckoutInfo { ref: string @@ -107,3 +110,108 @@ export function getRefSpec(ref: string, commit: string): string[] { return [`+${ref}:${ref}`] } } + +export async function checkCommitInfo( + token: string, + commitInfo: string, + repositoryOwner: string, + repositoryName: string, + ref: string, + commit: string +): Promise<void> { + try { + // GHES? + if (isGhes()) { + return + } + + // Auth token? + if (!token) { + return + } + + // Public PR synchronize, for workflow repo? + if ( + fromPayload('repository.private') !== false || + github.context.eventName !== 'pull_request' || + fromPayload('action') !== 'synchronize' || + repositoryOwner !== github.context.repo.owner || + repositoryName !== github.context.repo.repo || + ref !== github.context.ref || + !ref.startsWith('refs/pull/') || + commit !== github.context.sha + ) { + return + } + + // Head SHA + const expectedHeadSha = fromPayload('after') + if (!expectedHeadSha) { + core.debug('Unable to determine head sha') + return + } + + // Base SHA + const expectedBaseSha = fromPayload('pull_request.base.sha') + if (!expectedBaseSha) { + core.debug('Unable to determine base sha') + return + } + + // Expected message? + const expectedMessage = `Merge ${expectedHeadSha} into ${expectedBaseSha}` + if (commitInfo.indexOf(expectedMessage) >= 0) { + return + } + + // Extract details from message + const match = commitInfo.match(/Merge ([0-9a-f]{40}) into ([0-9a-f]{40})/) + if (!match) { + core.debug('Unexpected message format') + return + } + + // Post telemetry + const actualHeadSha = match[1] + if (actualHeadSha !== expectedHeadSha) { + core.debug( + `Expected head sha ${expectedHeadSha}; actual head sha ${actualHeadSha}` + ) + const octokit = new github.GitHub(token, { + userAgent: `actions-checkout-tracepoint/1.0 (code=STALE_MERGE;owner=${repositoryOwner};repo=${repositoryName};pr=${fromPayload( + 'number' + )};run_id=${ + process.env['GITHUB_RUN_ID'] + };expected_head_sha=${expectedHeadSha};actual_head_sha=${actualHeadSha})` + }) + await octokit.repos.get({owner: repositoryOwner, repo: repositoryName}) + } + } catch (err) { + core.debug(`Error when validating commit info: ${err.stack}`) + } +} + +function fromPayload(path: string): any { + return select(github.context.payload, path) +} + +function select(obj: any, path: string): any { + if (!obj) { + return undefined + } + + const i = path.indexOf('.') + if (i < 0) { + return obj[path] + } + + const key = path.substr(0, i) + return select(obj[key], path.substr(i + 1)) +} + +function isGhes(): boolean { + const ghUrl = new URL( + process.env['GITHUB_SERVER_URL'] || 'https://github.com' + ) + return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM' +} |
