Read-only mirror — the public repositories of the Forgejo instance, refreshed every 10 minutes. The live instance (fg.dieschoenewolke.de) is reachable only over the VPN; clone here with https://git.dieschoenewolke.de/git/<owner>/<repo>.git.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/git-command-manager.ts7
-rw-r--r--src/git-source-provider.ts12
-rw-r--r--src/ref-helper.ts108
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'
+}