From f3b199b7edcd73954c1e22a306ed88c649127bec Mon Sep 17 00:00:00 2001 From: Nicolas Schweitzer Date: Thu, 19 Dec 2024 15:30:48 +0100 Subject: [PATCH 1/3] feat(git config): Set default user.name and user.email in git config --- README.md | 4 ---- action.yml | 6 ++++++ dist/index.js | 3 +++ src/git-source-provider.ts | 8 ++++++++ src/git-source-settings.ts | 5 +++++ src/input-helper.ts | 4 ++++ 6 files changed, 26 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b0f6224f1..9b666c80f 100644 --- a/README.md +++ b/README.md @@ -281,8 +281,6 @@ jobs: - run: | date > generated.txt # Note: the following account information will not work on GHES - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add . git commit -m "generated" git push @@ -305,8 +303,6 @@ jobs: - run: | date > generated.txt # Note: the following account information will not work on GHES - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add . git commit -m "generated" git push diff --git a/action.yml b/action.yml index 6842eb843..2e379126f 100644 --- a/action.yml +++ b/action.yml @@ -22,6 +22,12 @@ inputs: [Learn more about creating and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) default: ${{ github.token }} + configure-user: + description: > + Whether to configure user.name and user.email in the local git config. + This is required to push a commit from a Github Action Workflow. + Set to `false` to disable the config. + default: true ssh-key: description: > SSH key used to fetch the repository. The SSH key is configured with the local diff --git a/dist/index.js b/dist/index.js index b0db71380..230e725f3 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1813,6 +1813,9 @@ function getInputs() { core.debug(`recursive submodules = ${result.nestedSubmodules}`); // Auth token result.authToken = core.getInput('token', { required: true }); + // Configure user + result.configureUser = + (core.getInput('configure-user') || 'true').toUpperCase() === 'TRUE' // SSH result.sshKey = core.getInput('ssh-key'); result.sshKnownHosts = core.getInput('ssh-known-hosts'); diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index 2d3513897..dcdb9b278 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -274,6 +274,14 @@ export async function getSource(settings: IGitSourceSettings): Promise { settings.commit, settings.githubServerUrl ) + if (settings.configureUser) { + if (!await git.configExists('user.name', true)) { + await git.config('user.name', 'github-action[bot]', true) + } + if (!await git.configExists('user.email', true)) { + await git.config('user.email', '41898282+github-actions[bot]@users.noreply.github.com', true) + } + } } finally { // Remove auth if (authHelper) { diff --git a/src/git-source-settings.ts b/src/git-source-settings.ts index 4e41ac302..e7ddb41cd 100644 --- a/src/git-source-settings.ts +++ b/src/git-source-settings.ts @@ -79,6 +79,11 @@ export interface IGitSourceSettings { */ authToken: string + /** + * Indicates whether to set a default user name and email in the local git config + */ + configureUser: boolean + /** * The SSH key to configure */ diff --git a/src/input-helper.ts b/src/input-helper.ts index 059232f5c..b1a2b7a4b 100644 --- a/src/input-helper.ts +++ b/src/input-helper.ts @@ -138,6 +138,10 @@ export async function getInputs(): Promise { // Auth token result.authToken = core.getInput('token', {required: true}) + // Configure user + result.configureUser = + (core.getInput('configure-user') || 'true').toUpperCase() === 'TRUE' + // SSH result.sshKey = core.getInput('ssh-key') result.sshKnownHosts = core.getInput('ssh-known-hosts') From 5fba9eb89980216c4b361e5fe35a04a2efc0cf97 Mon Sep 17 00:00:00 2001 From: Nicolas Schweitzer Date: Tue, 21 Jan 2025 18:50:25 +0100 Subject: [PATCH 2/3] codereview: define a git-user slug instead of a true/false config --- README.md | 6 ++++++ action.yml | 8 ++++---- dist/index.js | 3 +-- src/git-source-provider.ts | 8 +++++--- src/git-source-settings.ts | 4 ++-- src/github-api-helper.ts | 12 ++++++++++++ src/input-helper.ts | 5 ++--- 7 files changed, 32 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9b666c80f..9683d93bd 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,12 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/ # # Default: ${{ github.token }} token: '' + + # Github slug used to configure local user.name and user.email for git. + # This is required to push a commit from a Github Action Workflow + # Set to '' to disable this configuration + # Default: "github-action[bot] + git-config: '' # SSH key used to fetch the repository. The SSH key is configured with the local # git config, which enables your scripts to run authenticated git commands. The diff --git a/action.yml b/action.yml index 2e379126f..d1a2902b4 100644 --- a/action.yml +++ b/action.yml @@ -22,12 +22,12 @@ inputs: [Learn more about creating and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) default: ${{ github.token }} - configure-user: + git-user: description: > - Whether to configure user.name and user.email in the local git config. + Github slug used to configure local user.name and user.email for git. This is required to push a commit from a Github Action Workflow. - Set to `false` to disable the config. - default: true + Set to '' to disable this configuration. + default: "github-action[bot]" ssh-key: description: > SSH key used to fetch the repository. The SSH key is configured with the local diff --git a/dist/index.js b/dist/index.js index 230e725f3..b5e352a4c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1814,8 +1814,7 @@ function getInputs() { // Auth token result.authToken = core.getInput('token', { required: true }); // Configure user - result.configureUser = - (core.getInput('configure-user') || 'true').toUpperCase() === 'TRUE' + result.gitUser = (core.getInput('git-user') || 'github-action[bot]') // SSH result.sshKey = core.getInput('ssh-key'); result.sshKnownHosts = core.getInput('ssh-known-hosts'); diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index dcdb9b278..bb4c5a5ca 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -274,12 +274,14 @@ export async function getSource(settings: IGitSourceSettings): Promise { settings.commit, settings.githubServerUrl ) - if (settings.configureUser) { + if (settings.gitUser) { if (!await git.configExists('user.name', true)) { - await git.config('user.name', 'github-action[bot]', true) + await git.config('user.name', settings.gitUser, true) } if (!await git.configExists('user.email', true)) { - await git.config('user.email', '41898282+github-actions[bot]@users.noreply.github.com', true) + + const userId = await githubApiHelper.getUserId(settings.gitUser, settings.authToken, settings.githubServerUrl); + await git.config('user.email', `${userId}+${settings.gitUser}@users.noreply.github.com`, true) } } } finally { diff --git a/src/git-source-settings.ts b/src/git-source-settings.ts index e7ddb41cd..9cc2919de 100644 --- a/src/git-source-settings.ts +++ b/src/git-source-settings.ts @@ -80,9 +80,9 @@ export interface IGitSourceSettings { authToken: string /** - * Indicates whether to set a default user name and email in the local git config + * A github user slug to set a default user name and email in the local git config */ - configureUser: boolean + gitUser: string /** * The SSH key to configure diff --git a/src/github-api-helper.ts b/src/github-api-helper.ts index 1ff27c2c7..b90b99077 100644 --- a/src/github-api-helper.ts +++ b/src/github-api-helper.ts @@ -143,3 +143,15 @@ async function downloadArchive( }) return Buffer.from(response.data as ArrayBuffer) // response.data is ArrayBuffer } + +export async function getUserId( + username: string, + authToken: string, + baseUrl?: string +): Promise { + const octokit = github.getOctokit(authToken, { + baseUrl: getServerApiUrl(baseUrl) + }) + const user = await octokit.rest.users.getByUsername({username,}); + return user.data.id +} diff --git a/src/input-helper.ts b/src/input-helper.ts index b1a2b7a4b..343f4a53c 100644 --- a/src/input-helper.ts +++ b/src/input-helper.ts @@ -138,9 +138,8 @@ export async function getInputs(): Promise { // Auth token result.authToken = core.getInput('token', {required: true}) - // Configure user - result.configureUser = - (core.getInput('configure-user') || 'true').toUpperCase() === 'TRUE' + // Git user + result.gitUser = core.getInput('git-user') || 'github-action[bot]' // SSH result.sshKey = core.getInput('ssh-key') From ab5d862ce859c0e3a909ea13d61a0112d9018d3b Mon Sep 17 00:00:00 2001 From: Nicolas Schweitzer Date: Wed, 22 Jan 2025 11:55:00 +0100 Subject: [PATCH 3/3] fix tests and update index.js --- README.md | 12 ++++++------ __test__/git-auth-helper.test.ts | 11 ++++++----- __test__/git-command-manager.test.ts | 4 ++-- __test__/git-directory-helper.test.ts | 4 ++-- __test__/input-helper.test.ts | 8 ++++---- __test__/ref-helper.test.ts | 4 ++-- __test__/retry-helper.test.ts | 2 +- dist/index.js | 23 +++++++++++++++++++++-- package-lock.json | 16 +++++++++------- src/git-source-provider.ts | 19 +++++++++++++------ src/github-api-helper.ts | 2 +- 11 files changed, 67 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 9683d93bd..53dcc750e 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,12 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/ # # Default: ${{ github.token }} token: '' - - # Github slug used to configure local user.name and user.email for git. - # This is required to push a commit from a Github Action Workflow - # Set to '' to disable this configuration - # Default: "github-action[bot] - git-config: '' + + # Github slug used to configure local user.name and user.email for git. This is + # required to push a commit from a Github Action Workflow. Set to '' to disable + # this configuration. + # Default: github-action[bot] + git-user: '' # SSH key used to fetch the repository. The SSH key is configured with the local # git config, which enables your scripts to run authenticated git commands. The diff --git a/__test__/git-auth-helper.test.ts b/__test__/git-auth-helper.test.ts index 7633704cc..6515ff8c7 100644 --- a/__test__/git-auth-helper.test.ts +++ b/__test__/git-auth-helper.test.ts @@ -1,12 +1,12 @@ import * as core from '@actions/core' import * as fs from 'fs' -import * as gitAuthHelper from '../lib/git-auth-helper' +import * as gitAuthHelper from '../src/git-auth-helper' import * as io from '@actions/io' import * as os from 'os' import * as path from 'path' -import * as stateHelper from '../lib/state-helper' -import {IGitCommandManager} from '../lib/git-command-manager' -import {IGitSourceSettings} from '../lib/git-source-settings' +import * as stateHelper from '../src/state-helper' +import {IGitCommandManager} from '../src/git-command-manager' +import {IGitSourceSettings} from '../src/git-source-settings' const isWindows = process.platform === 'win32' const testWorkspace = path.join(__dirname, '_temp', 'git-auth-helper') @@ -824,7 +824,8 @@ async function setup(testName: string): Promise { sshUser: '', workflowOrganizationId: 123456, setSafeDirectory: true, - githubServerUrl: githubServerUrl + githubServerUrl: githubServerUrl, + gitUser: 'github-action[bot]' } } diff --git a/__test__/git-command-manager.test.ts b/__test__/git-command-manager.test.ts index cea73d4dd..414c070aa 100644 --- a/__test__/git-command-manager.test.ts +++ b/__test__/git-command-manager.test.ts @@ -1,6 +1,6 @@ import * as exec from '@actions/exec' -import * as fshelper from '../lib/fs-helper' -import * as commandManager from '../lib/git-command-manager' +import * as fshelper from '../src/fs-helper' +import * as commandManager from '../src/git-command-manager' let git: commandManager.IGitCommandManager let mockExec = jest.fn() diff --git a/__test__/git-directory-helper.test.ts b/__test__/git-directory-helper.test.ts index 22e9ae6d4..8899e5105 100644 --- a/__test__/git-directory-helper.test.ts +++ b/__test__/git-directory-helper.test.ts @@ -1,9 +1,9 @@ import * as core from '@actions/core' import * as fs from 'fs' -import * as gitDirectoryHelper from '../lib/git-directory-helper' +import * as gitDirectoryHelper from '../src/git-directory-helper' import * as io from '@actions/io' import * as path from 'path' -import {IGitCommandManager} from '../lib/git-command-manager' +import {IGitCommandManager} from '../src/git-command-manager' const testWorkspace = path.join(__dirname, '_temp', 'git-directory-helper') let repositoryPath: string diff --git a/__test__/input-helper.test.ts b/__test__/input-helper.test.ts index 9514cb42d..e57da83a1 100644 --- a/__test__/input-helper.test.ts +++ b/__test__/input-helper.test.ts @@ -1,10 +1,10 @@ import * as core from '@actions/core' -import * as fsHelper from '../lib/fs-helper' +import * as fsHelper from '../src/fs-helper' import * as github from '@actions/github' -import * as inputHelper from '../lib/input-helper' +import * as inputHelper from '../src/input-helper' import * as path from 'path' -import * as workflowContextHelper from '../lib/workflow-context-helper' -import {IGitSourceSettings} from '../lib/git-source-settings' +import * as workflowContextHelper from '../src/workflow-context-helper' +import {IGitSourceSettings} from '../src/git-source-settings' const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE'] const gitHubWorkspace = path.resolve('/checkout-tests/workspace') diff --git a/__test__/ref-helper.test.ts b/__test__/ref-helper.test.ts index 5c8d76b87..c78b976be 100644 --- a/__test__/ref-helper.test.ts +++ b/__test__/ref-helper.test.ts @@ -1,6 +1,6 @@ import * as assert from 'assert' -import * as refHelper from '../lib/ref-helper' -import {IGitCommandManager} from '../lib/git-command-manager' +import * as refHelper from '../src/ref-helper' +import {IGitCommandManager} from '../src/git-command-manager' const commit = '1234567890123456789012345678901234567890' let git: IGitCommandManager diff --git a/__test__/retry-helper.test.ts b/__test__/retry-helper.test.ts index a5d3f7909..373ccbb8c 100644 --- a/__test__/retry-helper.test.ts +++ b/__test__/retry-helper.test.ts @@ -1,5 +1,5 @@ import * as core from '@actions/core' -import {RetryHelper} from '../lib/retry-helper' +import {RetryHelper} from '../src/retry-helper' let info: string[] let retryHelper: any diff --git a/dist/index.js b/dist/index.js index b5e352a4c..1f1365869 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1357,6 +1357,15 @@ function getSource(settings) { core.setOutput('commit', commitSHA.trim()); // Check for incorrect pull request merge commit yield refHelper.checkCommitInfo(settings.authToken, commitInfo, settings.repositoryOwner, settings.repositoryName, settings.ref, settings.commit, settings.githubServerUrl); + if (settings.gitUser) { + if (!(yield git.configExists('user.name', true))) { + yield git.config('user.name', settings.gitUser, true); + } + if (!(yield git.configExists('user.email', true))) { + const userId = yield githubApiHelper.getUserId(settings.gitUser, settings.authToken, settings.githubServerUrl); + yield git.config('user.email', `${userId}+${settings.gitUser}@users.noreply.github.com`, true); + } + } } finally { // Remove auth @@ -1546,6 +1555,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge Object.defineProperty(exports, "__esModule", ({ value: true })); exports.downloadRepository = downloadRepository; exports.getDefaultBranch = getDefaultBranch; +exports.getUserId = getUserId; const assert = __importStar(__nccwpck_require__(9491)); const core = __importStar(__nccwpck_require__(2186)); const fs = __importStar(__nccwpck_require__(7147)); @@ -1663,6 +1673,15 @@ function downloadArchive(authToken, owner, repo, ref, commit, baseUrl) { return Buffer.from(response.data); // response.data is ArrayBuffer }); } +function getUserId(username, authToken, baseUrl) { + return __awaiter(this, void 0, void 0, function* () { + const octokit = github.getOctokit(authToken, { + baseUrl: (0, url_helper_1.getServerApiUrl)(baseUrl) + }); + const user = yield octokit.rest.users.getByUsername({ username, }); + return user.data.id; + }); +} /***/ }), @@ -1813,8 +1832,8 @@ function getInputs() { core.debug(`recursive submodules = ${result.nestedSubmodules}`); // Auth token result.authToken = core.getInput('token', { required: true }); - // Configure user - result.gitUser = (core.getInput('git-user') || 'github-action[bot]') + // Git user + result.gitUser = core.getInput('git-user') || 'github-action[bot]'; // SSH result.sshKey = core.getInput('ssh-key'); result.sshKnownHosts = core.getInput('ssh-known-hosts'); diff --git a/package-lock.json b/package-lock.json index 25753a2fd..171933245 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2502,10 +2502,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5528,12 +5529,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { diff --git a/src/git-source-provider.ts b/src/git-source-provider.ts index bb4c5a5ca..bb44f11ee 100644 --- a/src/git-source-provider.ts +++ b/src/git-source-provider.ts @@ -275,14 +275,21 @@ export async function getSource(settings: IGitSourceSettings): Promise { settings.githubServerUrl ) if (settings.gitUser) { - if (!await git.configExists('user.name', true)) { + if (!(await git.configExists('user.name', true))) { await git.config('user.name', settings.gitUser, true) } - if (!await git.configExists('user.email', true)) { - - const userId = await githubApiHelper.getUserId(settings.gitUser, settings.authToken, settings.githubServerUrl); - await git.config('user.email', `${userId}+${settings.gitUser}@users.noreply.github.com`, true) - } + if (!(await git.configExists('user.email', true))) { + const userId = await githubApiHelper.getUserId( + settings.gitUser, + settings.authToken, + settings.githubServerUrl + ) + await git.config( + 'user.email', + `${userId}+${settings.gitUser}@users.noreply.github.com`, + true + ) + } } } finally { // Remove auth diff --git a/src/github-api-helper.ts b/src/github-api-helper.ts index b90b99077..8e0cd0dd3 100644 --- a/src/github-api-helper.ts +++ b/src/github-api-helper.ts @@ -152,6 +152,6 @@ export async function getUserId( const octokit = github.getOctokit(authToken, { baseUrl: getServerApiUrl(baseUrl) }) - const user = await octokit.rest.users.getByUsername({username,}); + const user = await octokit.rest.users.getByUsername({username}) return user.data.id }