diff --git a/README.md b/README.md
index e4888ae..3ba42cd 100644
--- a/README.md
+++ b/README.md
@@ -27,17 +27,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- # Perform a minimal checkout to set up this repository for the rest of the
- # workflow.
- #
- # This step must be configured exactly as below: using different
- # actions/checkout arguments is not supported.
- - name: Checkout this repository
- uses: actions/checkout@v4
- with:
- filter: tree:0
-
- # Run the estimation tool
- name: Run sizeup
# TODO: Replace the version below with your desired version.
uses: lerebear/sizeup-action@v0.4.2
diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts
index 7ed6295..315d725 100644
--- a/__tests__/main.test.ts
+++ b/__tests__/main.test.ts
@@ -9,21 +9,31 @@
import * as core from '@actions/core'
import * as main from '../src/main'
import * as initializer from '../src/initializer'
+import { Git } from '../src/git'
import * as github from '@actions/github'
function pullRequestEventContext(overrides = {}): object {
return {
eventName: 'pull_request',
+ repo: {
+ owner: 'lerebear',
+ name: 'sizeup-action'
+ },
payload: {
pull_request: {
base: {
+ ref: 'main',
repo: {
+ full_name: 'lerebear/sizeup-action',
name: 'sizeup-action',
owner: {
login: 'lerebear'
}
}
},
+ head: {
+ ref: 'topic'
+ },
labels: [],
number: 1,
user: {
@@ -69,9 +79,12 @@ describe('action', () => {
// Shallow clone original @actions/github context
const originalContext = { ...github.context }
+ // Mock cloning the repo
+ jest.spyOn(Git.prototype, 'clone').mockImplementation(async () => {})
+
// Mock the diff that we use for evaluation.
jest
- .spyOn(initializer, 'fetchDiff')
+ .spyOn(Git.prototype, 'diff')
.mockImplementation(async () =>
Promise.resolve(
'--- README.md 2023-10-16 16:35:38\n+++ README-AGAIN.md 2023-10-16 16:36:07\n@@ -0,0 +1 @@\n+# Hello, World!'
diff --git a/badges/coverage.svg b/badges/coverage.svg
index d179b1d..344c2dc 100644
--- a/badges/coverage.svg
+++ b/badges/coverage.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/dist/index.js b/dist/index.js
index 8cef7fe..e38cc15 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -16317,6 +16317,95 @@ function wrappy (fn, cb) {
}
+/***/ }),
+
+/***/ 6350:
+/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
+
+"use strict";
+
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+};
+Object.defineProperty(exports, "__esModule", ({ value: true }));
+exports.Git = void 0;
+const core = __importStar(__nccwpck_require__(2186));
+const lib = __importStar(__nccwpck_require__(9103));
+class Git {
+ client;
+ constructor() {
+ const basicCredential = Buffer.from(`x-access-token:${core.getInput('token')}`, 'utf8').toString('base64');
+ const authorizationHeader = `AUTHORIZATION: basic ${basicCredential}`;
+ core.setSecret(basicCredential);
+ this.client = lib.simpleGit('.', {
+ trimmed: true,
+ config: [`http.extraheader=${authorizationHeader}`]
+ });
+ }
+ /**
+ * Clones the repository from which this workflow was triggered.
+ *
+ * @param repo The repository to clone in the format "/"
+ * @param headRef The single branch to clone, which should correspond to the
+ * head ref of the pull request that triggered this workflow. This is
+ * required for efficiency.
+ * @param targetDirectory The directory in which to clone the repository.
+ */
+ async clone(repo, headRef, targetDirectory = '.') {
+ core.info(`Cloning ${repo} with the single branch "${headRef}"`);
+ await this.client.clone(`https://github.com/${repo}`, targetDirectory, [
+ `--branch=${headRef}`,
+ '--filter=tree:0',
+ '--no-tags',
+ '--single-branch'
+ ]);
+ }
+ /**
+ * Retrieves the diff of the pull request that triggered this workflow which we
+ * will use for evaluation.
+ *
+ * @param baseRef The base branch relative to which we should produce a diff. This method assumes
+ * that the head ref containing the changes has already been fetched.
+ * @returns The diff of the given pull request or `undefined` if we failed to retrieve it.
+ */
+ async diff(baseRef) {
+ core.debug(`Fetching base ref "${baseRef}"`);
+ await this.client.fetch([
+ 'origin',
+ `+${baseRef}:${baseRef}`,
+ `--filter=tree:0`,
+ '--no-tags',
+ '--prune',
+ '--no-recurse-submodules'
+ ]);
+ const diffArgs = ['--merge-base', baseRef].concat(core.getInput('git-diff-options').split(/\s+/));
+ core.info(`Retrieving diff with \`git diff ${diffArgs.join(' ')}\``);
+ return this.client.diff(diffArgs);
+ }
+}
+exports.Git = Git;
+
+
/***/ }),
/***/ 9477:
@@ -16348,13 +16437,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
-exports.fetchDiff = exports.pullRequestAuthorHasNotOptedIn = exports.workflowTriggeredForUnsupportedEvent = exports.loadConfiguration = void 0;
+exports.pullRequestAuthorHasNotOptedIn = exports.loadConfiguration = void 0;
const core = __importStar(__nccwpck_require__(2186));
-const github = __importStar(__nccwpck_require__(5438));
const fs = __importStar(__nccwpck_require__(7147));
const path = __importStar(__nccwpck_require__(1017));
const YAML = __importStar(__nccwpck_require__(4083));
-const simple_git_1 = __nccwpck_require__(9103);
/**
* Loads either the configuration file provided to the workflow, or the default
* configuration file from "./config/default.yaml".
@@ -16373,69 +16460,17 @@ function loadConfiguration() {
return YAML.parse(fs.readFileSync(configFile, 'utf8'));
}
exports.loadConfiguration = loadConfiguration;
-function workflowTriggeredForUnsupportedEvent() {
- if (github.context.eventName !== 'pull_request') {
- core.setFailed("This action is only supported on the 'pull_request' event, " +
- `but it was triggered for '${github.context.eventName}'`);
- return true;
- }
- return false;
-}
-exports.workflowTriggeredForUnsupportedEvent = workflowTriggeredForUnsupportedEvent;
-function pullRequestAuthorHasNotOptedIn(config, pullRequest) {
+function pullRequestAuthorHasNotOptedIn(config, pull) {
const usersWhoHaveOptedin = config.optIns || [];
if (usersWhoHaveOptedin.length &&
- !usersWhoHaveOptedin.find((login) => login === pullRequest.user.login)) {
- core.info(`Skipping evaluation because pull request author @${pullRequest.user.login} has not opted` +
+ !usersWhoHaveOptedin.find((login) => login === pull.user.login)) {
+ core.info(`Skipping evaluation because pull request author @${pull.user.login} has not opted` +
' into this workflow');
return true;
}
return false;
}
exports.pullRequestAuthorHasNotOptedIn = pullRequestAuthorHasNotOptedIn;
-/**
- * Retrieves the diff of the pull request that triggered this workflow which we
- * will use for evaluation.
- *
- * @param pull The pull request that triggered this workflow.
- * @returns The diff of the given pull request or `undefined` if we failed to retrieve it.
- */
-async function fetchDiff(pull) {
- const git = (0, simple_git_1.simpleGit)('.', { trimmed: true });
- // let baseRefExists = false
- // try {
- // baseRefExists = !!(await git.raw('rev-parse', '--verify', pull.base.ref))
- // } catch (e) {
- // core.error(
- // `Error from 'git rev-parse --verfy ${pull.base.ref}': ${
- // (e as Error).message
- // }`
- // )
- // }
- // if (!baseRefExists) {
- // core.setFailed(
- // `Could not find pull request base branch ${pull.base.ref}. ` +
- // `Please make sure actions/checkout was used beforehand to fetch ${pull.base.ref}.`
- // )
- // return
- // }
- core.debug(`Fetching base ref "${pull.base.ref}" and head ref "${pull.head.ref}"`);
- await git.fetch([
- 'origin',
- `+${pull.base.ref}:${pull.base.ref}`,
- `+${pull.head.ref}:${pull.head.ref}`,
- `--filter=tree:0`,
- '--no-tags',
- '--prune',
- '--no-recurse-submodules'
- ]);
- core.debug(`Switching to head ref "${pull.head.ref}"`);
- await git.raw('switch', pull.head.ref);
- const diffArgs = ['--merge-base', pull.base.ref].concat(core.getInput('git-diff-options').split(/\s+/));
- core.info(`Retrieving diff with \`git diff ${diffArgs.join(' ')}\``);
- return git.diff(diffArgs);
-}
-exports.fetchDiff = fetchDiff;
/***/ }),
@@ -16477,6 +16512,7 @@ const YAML = __importStar(__nccwpck_require__(4083));
const fs = __importStar(__nccwpck_require__(7147));
const path = __importStar(__nccwpck_require__(1017));
const initializer_1 = __nccwpck_require__(9477);
+const git_1 = __nccwpck_require__(6350);
const DEFAULT_LABEL_PREFIX = 'sizeup/';
const DEFAULT_COMMENT_TEMPLATE = `
👋 @{{author}} this pull request exceeds the configured reviewability score threshold of {{threshold}}. Your actual score was {{score}}.
@@ -16493,13 +16529,18 @@ const DEFAULT_SCORE_THRESHOLD = 100;
*/
async function run() {
try {
- if ((0, initializer_1.workflowTriggeredForUnsupportedEvent)())
+ if (github.context.eventName !== 'pull_request') {
+ core.setFailed("This action is only supported on the 'pull_request' event, " +
+ `but it was triggered for '${github.context.eventName}'`);
return;
- const config = (0, initializer_1.loadConfiguration)();
+ }
const pullRequest = github.context.payload.pull_request;
+ const git = new git_1.Git();
+ await git.clone(pullRequest.base.repo.full_name, pullRequest.head.ref);
+ const config = (0, initializer_1.loadConfiguration)();
if ((0, initializer_1.pullRequestAuthorHasNotOptedIn)(config, pullRequest))
return;
- const diff = await (0, initializer_1.fetchDiff)(pullRequest);
+ const diff = await git.diff(pullRequest.base.ref);
if (!diff)
return;
const score = await evaluatePullRequest(pullRequest, diff, config);
@@ -16523,7 +16564,7 @@ exports.run = run;
* @returns The score that the pull request received
*/
async function evaluatePullRequest(pull, diff, config) {
- const pullRequestNickname = `${pull.base.repo.owner.login}/${pull.base.repo.name}#${pull.number}`;
+ const pullRequestNickname = `${pull.base.repo.full_name}#${pull.number}`;
core.info(`Evaluating pull request ${pullRequestNickname}`);
let sizeupConfigFile = undefined;
if (config.sizeup) {
diff --git a/src/git.ts b/src/git.ts
new file mode 100644
index 0000000..0d2b15d
--- /dev/null
+++ b/src/git.ts
@@ -0,0 +1,70 @@
+import * as core from '@actions/core'
+import * as lib from 'simple-git'
+
+export class Git {
+ private client: lib.SimpleGit
+
+ constructor() {
+ const basicCredential = Buffer.from(
+ `x-access-token:${core.getInput('token')}`,
+ 'utf8'
+ ).toString('base64')
+ const authorizationHeader = `AUTHORIZATION: basic ${basicCredential}`
+ core.setSecret(basicCredential)
+
+ this.client = lib.simpleGit('.', {
+ trimmed: true,
+ config: [`http.extraheader=${authorizationHeader}`]
+ })
+ }
+
+ /**
+ * Clones the repository from which this workflow was triggered.
+ *
+ * @param repo The repository to clone in the format "/"
+ * @param headRef The single branch to clone, which should correspond to the
+ * head ref of the pull request that triggered this workflow. This is
+ * required for efficiency.
+ * @param targetDirectory The directory in which to clone the repository.
+ */
+ async clone(
+ repo: string,
+ headRef: string,
+ targetDirectory = '.'
+ ): Promise {
+ core.info(`Cloning ${repo} with the single branch "${headRef}"`)
+
+ await this.client.clone(`https://github.com/${repo}`, targetDirectory, [
+ `--branch=${headRef}`,
+ '--filter=tree:0',
+ '--no-tags',
+ '--single-branch'
+ ])
+ }
+
+ /**
+ * Retrieves the diff of the pull request that triggered this workflow which we
+ * will use for evaluation.
+ *
+ * @param baseRef The base branch relative to which we should produce a diff. This method assumes
+ * that the head ref containing the changes has already been fetched.
+ * @returns The diff of the given pull request or `undefined` if we failed to retrieve it.
+ */
+ async diff(baseRef: string): Promise {
+ core.debug(`Fetching base ref "${baseRef}"`)
+ await this.client.fetch([
+ 'origin',
+ `+${baseRef}:${baseRef}`,
+ `--filter=tree:0`,
+ '--no-tags',
+ '--prune',
+ '--no-recurse-submodules'
+ ])
+
+ const diffArgs = ['--merge-base', baseRef].concat(
+ core.getInput('git-diff-options').split(/\s+/)
+ )
+ core.info(`Retrieving diff with \`git diff ${diffArgs.join(' ')}\``)
+ return this.client.diff(diffArgs)
+ }
+}
diff --git a/src/initializer.ts b/src/initializer.ts
index c4eb934..f72286c 100644
--- a/src/initializer.ts
+++ b/src/initializer.ts
@@ -1,10 +1,8 @@
import * as core from '@actions/core'
-import * as github from '@actions/github'
import { Configuration } from './configuration'
import * as fs from 'fs'
import * as path from 'path'
import * as YAML from 'yaml'
-import { simpleGit } from 'simple-git'
import { PullRequest } from '@octokit/webhooks-types' // eslint-disable-line import/no-unresolved
/**
@@ -26,32 +24,18 @@ export function loadConfiguration(): Configuration {
return YAML.parse(fs.readFileSync(configFile, 'utf8')) as Configuration
}
-export function workflowTriggeredForUnsupportedEvent(): boolean {
- if (github.context.eventName !== 'pull_request') {
- core.setFailed(
- "This action is only supported on the 'pull_request' event, " +
- `but it was triggered for '${github.context.eventName}'`
- )
- return true
- }
-
- return false
-}
-
export function pullRequestAuthorHasNotOptedIn(
config: Configuration,
- pullRequest: PullRequest
+ pull: PullRequest
): boolean {
const usersWhoHaveOptedin = config.optIns || []
if (
usersWhoHaveOptedin.length &&
- !usersWhoHaveOptedin.find(
- (login: string) => login === pullRequest.user.login
- )
+ !usersWhoHaveOptedin.find((login: string) => login === pull.user.login)
) {
core.info(
- `Skipping evaluation because pull request author @${pullRequest.user.login} has not opted` +
+ `Skipping evaluation because pull request author @${pull.user.login} has not opted` +
' into this workflow'
)
return true
@@ -59,58 +43,3 @@ export function pullRequestAuthorHasNotOptedIn(
return false
}
-
-/**
- * Retrieves the diff of the pull request that triggered this workflow which we
- * will use for evaluation.
- *
- * @param pull The pull request that triggered this workflow.
- * @returns The diff of the given pull request or `undefined` if we failed to retrieve it.
- */
-export async function fetchDiff(
- pull: PullRequest
-): Promise {
- const git = simpleGit('.', { trimmed: true })
-
- // let baseRefExists = false
- // try {
- // baseRefExists = !!(await git.raw('rev-parse', '--verify', pull.base.ref))
- // } catch (e) {
- // core.error(
- // `Error from 'git rev-parse --verfy ${pull.base.ref}': ${
- // (e as Error).message
- // }`
- // )
- // }
-
- // if (!baseRefExists) {
- // core.setFailed(
- // `Could not find pull request base branch ${pull.base.ref}. ` +
- // `Please make sure actions/checkout was used beforehand to fetch ${pull.base.ref}.`
- // )
- // return
- // }
-
- core.debug(
- `Fetching base ref "${pull.base.ref}" and head ref "${pull.head.ref}"`
- )
-
- await git.fetch([
- 'origin',
- `+${pull.base.ref}:${pull.base.ref}`,
- `+${pull.head.ref}:${pull.head.ref}`,
- `--filter=tree:0`,
- '--no-tags',
- '--prune',
- '--no-recurse-submodules'
- ])
-
- core.debug(`Switching to head ref "${pull.head.ref}"`)
- await git.raw('switch', pull.head.ref)
-
- const diffArgs = ['--merge-base', pull.base.ref].concat(
- core.getInput('git-diff-options').split(/\s+/)
- )
- core.info(`Retrieving diff with \`git diff ${diffArgs.join(' ')}\``)
- return git.diff(diffArgs)
-}
diff --git a/src/main.ts b/src/main.ts
index cf531cc..03f5256 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -7,11 +7,10 @@ import * as fs from 'fs'
import * as path from 'path'
import { Configuration } from './configuration'
import {
- fetchDiff,
loadConfiguration,
- pullRequestAuthorHasNotOptedIn,
- workflowTriggeredForUnsupportedEvent
+ pullRequestAuthorHasNotOptedIn
} from './initializer'
+import { Git } from './git'
const DEFAULT_LABEL_PREFIX = 'sizeup/'
const DEFAULT_COMMENT_TEMPLATE = `
@@ -30,14 +29,23 @@ const DEFAULT_SCORE_THRESHOLD = 100
*/
export async function run(): Promise {
try {
- if (workflowTriggeredForUnsupportedEvent()) return
+ if (github.context.eventName !== 'pull_request') {
+ core.setFailed(
+ "This action is only supported on the 'pull_request' event, " +
+ `but it was triggered for '${github.context.eventName}'`
+ )
+ return
+ }
- const config = loadConfiguration()
const pullRequest = github.context.payload.pull_request as PullRequest
+ const git = new Git()
+ await git.clone(pullRequest.base.repo.full_name, pullRequest.head.ref)
+
+ const config = loadConfiguration()
if (pullRequestAuthorHasNotOptedIn(config, pullRequest)) return
- const diff = await fetchDiff(pullRequest)
+ const diff = await git.diff(pullRequest.base.ref)
if (!diff) return
const score = await evaluatePullRequest(pullRequest, diff, config)
@@ -64,7 +72,7 @@ async function evaluatePullRequest(
diff: string,
config: Configuration
): Promise {
- const pullRequestNickname = `${pull.base.repo.owner.login}/${pull.base.repo.name}#${pull.number}`
+ const pullRequestNickname = `${pull.base.repo.full_name}#${pull.number}`
core.info(`Evaluating pull request ${pullRequestNickname}`)
let sizeupConfigFile = undefined