Skip to content

Commit

Permalink
telemetry for incorrect merge commit (#253)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsciple authored May 21, 2020
1 parent df86c82 commit 2ff2fbd
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 7 deletions.
98 changes: 95 additions & 3 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3359,7 +3359,7 @@ module.exports = {"name":"@octokit/rest","version":"16.43.1","publishConfig":{"a
/***/ }),

/***/ 227:
/***/ (function(__unusedmodule, exports) {
/***/ (function(__unusedmodule, exports, __webpack_require__) {

"use strict";

Expand All @@ -3372,7 +3372,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const url_1 = __webpack_require__(835);
const core = __importStar(__webpack_require__(470));
const github = __importStar(__webpack_require__(469));
function getCheckoutInfo(git, ref, commit) {
return __awaiter(this, void 0, void 0, function* () {
if (!git) {
Expand Down Expand Up @@ -3468,6 +3478,85 @@ function getRefSpec(ref, commit) {
}
}
exports.getRefSpec = getRefSpec;
function checkCommitInfo(token, commitInfo, repositoryOwner, repositoryName, ref, commit) {
return __awaiter(this, void 0, void 0, function* () {
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})`
});
yield octokit.repos.get({ owner: repositoryOwner, repo: repositoryName });
}
}
catch (err) {
core.debug(`Error when validating commit info: ${err.stack}`);
}
});
}
exports.checkCommitInfo = checkCommitInfo;
function fromPayload(path) {
return select(github.context.payload, path);
}
function select(obj, path) {
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() {
const ghUrl = new url_1.URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
return ghUrl.hostname.toUpperCase() !== 'github.com';
}


/***/ }),
Expand Down Expand Up @@ -5718,7 +5807,8 @@ class GitCommandManager {
}
log1() {
return __awaiter(this, void 0, void 0, function* () {
yield this.execGit(['log', '-1']);
const output = yield this.execGit(['log', '-1']);
return output.stdout;
});
}
remoteAdd(remoteName, remoteUrl) {
Expand Down Expand Up @@ -6057,7 +6147,9 @@ function getSource(settings) {
}
}
// Dump some info about the checked out commit
yield git.log1();
const commitInfo = yield git.log1();
// Check for incorrect pull request merge commit
yield refHelper.checkCommitInfo(settings.authToken, commitInfo, settings.repositoryOwner, settings.repositoryName, settings.ref, settings.commit);
}
finally {
// Remove auth
Expand Down
7 changes: 4 additions & 3 deletions src/git-command-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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> {
Expand Down
12 changes: 11 additions & 1 deletion src/git-source-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
108 changes: 108 additions & 0 deletions src/ref-helper.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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'
}

0 comments on commit 2ff2fbd

Please sign in to comment.