Skip to content

Commit 9f01b63

Browse files
committed
feat: Add support for remote GitHub repository + working directory (#2)
1 parent de9b9be commit 9f01b63

6 files changed

Lines changed: 133 additions & 46 deletions

File tree

__tests__/git.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ describe('Git CLI', () => {
182182

183183
describe('git add', () => {
184184
beforeEach(() => {
185-
jest.spyOn(cwd, 'getWorkspace').mockReturnValue('/test-workspace')
185+
jest.spyOn(cwd, 'getWorkspace').mockReturnValue('test-workspace/')
186186
})
187187

188188
it('should ensure file paths are within curent working directory', async () => {
@@ -191,7 +191,7 @@ describe('Git CLI', () => {
191191
await addFileChanges(['*.ts', '~/.bashrc'])
192192
expect(execMock).toHaveBeenCalledWith(
193193
'git',
194-
['add', '--', '/test-workspace/*.ts', '/test-workspace/~/.bashrc'],
194+
['add', '--', 'test-workspace/*.ts', 'test-workspace/~/.bashrc'],
195195
expect.objectContaining({
196196
listeners: { stdline: expect.anything(), errline: expect.anything() },
197197
})

action.yml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,23 @@ inputs:
1515
Directory containing files to be committed. Default: GitHub workspace directory (root of repository).
1616
required: false
1717
default: ''
18+
workdir:
19+
description: |
20+
Directory where the action should run. Default: GitHub workspace directory (root of repository from where the GH Workflow is triggered).
21+
required: false
22+
default: ''
1823
commit-message:
1924
description: |
2025
Commit message for the file changes.
2126
required: false
22-
repository:
27+
owner:
2328
description: |
24-
Repository name including owner (e.g. owner/repo). Default: Workflow triggered repository.
29+
GitHub repository owner (user or organization), defaults to the repo invoking the action.
30+
required: false
31+
repo:
32+
description: |
33+
GitHub repository name, defaults to the repo invoking the action.
2534
required: false
26-
default: ''
2735
branch-name:
2836
description: |
2937
Branch to commit to. Default: Workflow triggered branch.

dist/index.js

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30023,6 +30023,7 @@ function execGit(args) {
3002330023
const debugOutput = [];
3002430024
const warningOutput = [];
3002530025
const errorOutput = [];
30026+
core.debug('execGit() - args: ' + JSON.stringify(args));
3002630027
yield (0, exec_1.exec)('git', args, {
3002730028
silent: true,
3002830029
ignoreReturnCode: true,
@@ -30067,8 +30068,15 @@ function pushCurrentBranch() {
3006730068
}
3006830069
function addFileChanges(globPatterns) {
3006930070
return __awaiter(this, void 0, void 0, function* () {
30071+
const cwd = (0, cwd_1.getCwd)();
3007030072
const workspace = (0, cwd_1.getWorkspace)();
30071-
const workspacePaths = globPatterns.map((p) => (0, node_path_1.join)(workspace, p));
30073+
const resolvedWorkspace = (0, node_path_1.resolve)(workspace);
30074+
core.debug('addFileChanges() - resolvedWorkspace: ' + JSON.stringify(resolvedWorkspace));
30075+
let workspacePaths = globPatterns;
30076+
if (resolvedWorkspace.includes(cwd)) {
30077+
core.notice('addFileChanges() - "workspace" is a subdirectory, updating globPatterns');
30078+
workspacePaths = globPatterns.map((p) => (0, node_path_1.join)((0, node_path_1.relative)(cwd, resolvedWorkspace), p));
30079+
}
3007230080
yield execGit(['add', '--', ...workspacePaths]);
3007330081
});
3007430082
}
@@ -30445,52 +30453,68 @@ const core = __importStar(__nccwpck_require__(7484));
3044530453
const graphql_1 = __nccwpck_require__(1422);
3044630454
const repo_1 = __nccwpck_require__(1839);
3044730455
const git_1 = __nccwpck_require__(1243);
30456+
const cwd_1 = __nccwpck_require__(9827);
3044830457
const input_1 = __nccwpck_require__(7797);
3044930458
const errors_1 = __nccwpck_require__(3916);
3045030459
function run() {
3045130460
return __awaiter(this, void 0, void 0, function* () {
3045230461
var _a, _b, _c, _d, _e, _f;
3045330462
try {
30463+
core.info('Getting info from GH Worklfow context');
3045430464
const { owner, repo, branch } = (0, repo_1.getContext)();
30455-
const inputRepository = (0, input_1.getInput)('repository');
30465+
core.info('Setting variables according to inputs and context');
30466+
core.debug('* branch');
3045630467
const inputBranch = (0, input_1.getInput)('branch-name');
30457-
if (inputBranch && inputBranch !== branch) {
30458-
yield (0, git_1.switchBranch)(inputBranch);
30468+
const selectedBranch = inputBranch ? inputBranch : branch;
30469+
core.debug('* owner');
30470+
const inputOwner = (0, input_1.getInput)('owner');
30471+
const selectedOwner = inputOwner ? inputOwner : owner;
30472+
core.debug('* repo');
30473+
const inputRepo = (0, input_1.getInput)('repo');
30474+
const selectedRepo = inputRepo ? inputRepo : repo;
30475+
if (selectedOwner == owner &&
30476+
selectedRepo == repo &&
30477+
selectedBranch !== branch) {
30478+
core.warning('Pushing local and current branch to remote before proceeding');
30479+
// Git commands
30480+
yield (0, git_1.switchBranch)(selectedBranch);
3045930481
yield (0, git_1.pushCurrentBranch)();
3046030482
}
30461-
const repositoryParts = inputRepository ? inputRepository.split('/') : [];
30462-
if (repositoryParts.length && repositoryParts.length != 2) {
30463-
throw new errors_1.InputRepositoryInvalid(inputRepository);
30464-
}
30465-
const currentOwner = repositoryParts.length ? repositoryParts[0] : owner;
30466-
const currentRepository = repositoryParts.length ? repositoryParts[1] : repo;
30467-
const currentBranch = inputBranch ? inputBranch : branch;
30468-
const repository = yield core.group(`fetching repository info for owner: ${currentOwner}, repo: ${currentRepository}, branch: ${currentBranch}`, () => __awaiter(this, void 0, void 0, function* () {
30483+
const repository = yield core.group(`fetching repository info for owner: ${selectedOwner}, repo: ${selectedRepo}, branch: ${selectedBranch}`, () => __awaiter(this, void 0, void 0, function* () {
3046930484
const startTime = Date.now();
30470-
const repositoryData = yield (0, graphql_1.getRepository)(currentOwner, currentRepository, currentBranch);
30485+
const repositoryData = yield (0, graphql_1.getRepository)(selectedOwner, selectedRepo, selectedBranch);
3047130486
const endTime = Date.now();
3047230487
core.debug(`time taken: ${(endTime - startTime).toString()} ms`);
3047330488
return repositoryData;
3047430489
}));
30490+
core.info('Checking remote branches');
3047530491
if (!repository.ref) {
30476-
if (inputBranch && currentBranch == inputBranch) {
30492+
if (inputBranch) {
3047730493
throw new errors_1.InputBranchNotFound(inputBranch);
3047830494
}
3047930495
else {
30480-
throw new errors_1.BranchNotFound(currentBranch);
30496+
throw new errors_1.BranchNotFound(branch);
3048130497
}
3048230498
}
30499+
core.info('Processing to create signed commit');
30500+
core.debug('Get last (current?) commit');
3048330501
const currentCommit = (_b = (_a = repository.ref.target.history) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b[0];
3048430502
if (!currentCommit) {
3048530503
throw new errors_1.BranchCommitNotFound(repository.ref.name);
3048630504
}
3048730505
let createdCommit;
3048830506
const filePaths = core.getMultilineInput('files');
3048930507
if (filePaths.length <= 0) {
30490-
core.debug('skip file commit, empty files input');
30508+
core.notice('skip file commit, empty files input');
3049130509
}
3049230510
else {
30493-
core.debug(`proceed with file commit, input: ${JSON.stringify(filePaths)}`);
30511+
core.debug(`Proceed with file commit, input: ${JSON.stringify(filePaths)}`);
30512+
const workdir = (0, cwd_1.getWorkdir)();
30513+
const cwd = (0, cwd_1.getCwd)();
30514+
if (cwd !== workdir) {
30515+
core.notice('Changing working directory to Workdir: ' + workdir);
30516+
process.chdir(workdir);
30517+
}
3049430518
yield (0, git_1.addFileChanges)(filePaths);
3049530519
const fileChanges = yield (0, git_1.getFileChanges)();
3049630520
const fileCount = ((_d = (_c = fileChanges.additions) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) +
@@ -30512,7 +30536,7 @@ function run() {
3051230536
const startTime = Date.now();
3051330537
const commitData = yield (0, graphql_1.createCommitOnBranch)(currentCommit, commitMessage, {
3051430538
repositoryNameWithOwner: repository.nameWithOwner,
30515-
branchName: currentBranch,
30539+
branchName: selectedBranch,
3051630540
}, fileChanges);
3051730541
const endTime = Date.now();
3051830542
core.debug(`time taken: ${(endTime - startTime).toString()} ms`);
@@ -30646,6 +30670,7 @@ var __importStar = (this && this.__importStar) || (function () {
3064630670
Object.defineProperty(exports, "__esModule", ({ value: true }));
3064730671
exports.getCwd = getCwd;
3064830672
exports.getWorkspace = getWorkspace;
30673+
exports.getWorkdir = getWorkdir;
3064930674
const core = __importStar(__nccwpck_require__(7484));
3065030675
const input_1 = __nccwpck_require__(7797);
3065130676
function getCwd() {
@@ -30660,6 +30685,13 @@ function getWorkspace() {
3066030685
core.debug(`workspace: ${workspace}`);
3066130686
return workspace;
3066230687
}
30688+
function getWorkdir() {
30689+
const workdir = (0, input_1.getInput)('workdir', {
30690+
default: process.env.GITHUB_WORKSPACE,
30691+
});
30692+
core.debug(`workdir: ${workdir}`);
30693+
return workdir;
30694+
}
3066330695

3066430696

3066530697
/***/ }),

src/git.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import * as core from '@actions/core'
22
import { exec } from '@actions/exec'
3-
import { join } from 'node:path'
3+
import { join, relative, resolve } from 'node:path'
44
import {
55
FileChanges,
66
FileAddition,
77
FileDeletion,
88
} from '@octokit/graphql-schema'
99

10-
import { getWorkspace } from './utils/cwd'
10+
import { getCwd, getWorkspace } from './utils/cwd'
1111

1212
async function execGit(args: string[]) {
1313
const debugOutput: string[] = []
1414
const warningOutput: string[] = []
1515
const errorOutput: string[] = []
1616

17+
core.debug('execGit() - args: ' + JSON.stringify(args))
1718
await exec('git', args, {
1819
silent: true,
1920
ignoreReturnCode: true,
@@ -53,8 +54,22 @@ export async function pushCurrentBranch() {
5354
}
5455

5556
export async function addFileChanges(globPatterns: string[]) {
57+
const cwd = getCwd()
5658
const workspace = getWorkspace()
57-
const workspacePaths = globPatterns.map((p) => join(workspace, p))
59+
const resolvedWorkspace = resolve(workspace)
60+
core.debug(
61+
'addFileChanges() - resolvedWorkspace: ' + JSON.stringify(resolvedWorkspace)
62+
)
63+
64+
let workspacePaths = globPatterns
65+
if (resolvedWorkspace.includes(cwd)) {
66+
core.notice(
67+
'addFileChanges() - "workspace" is a subdirectory, updating globPatterns'
68+
)
69+
workspacePaths = globPatterns.map((p) =>
70+
join(relative(cwd, resolvedWorkspace), p)
71+
)
72+
}
5873

5974
await execGit(['add', '--', ...workspacePaths])
6075
}

src/main.ts

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
pushCurrentBranch,
1414
switchBranch,
1515
} from './git'
16+
import { getCwd, getWorkdir } from './utils/cwd'
1617
import { getInput } from './utils/input'
1718
import {
1819
NoFileChanges,
@@ -24,45 +25,61 @@ import {
2425

2526
export async function run(): Promise<void> {
2627
try {
28+
core.info('Getting info from GH Worklfow context')
2729
const { owner, repo, branch } = getContext()
28-
const inputRepository = getInput('repository')
30+
31+
core.info('Setting variables according to inputs and context')
32+
core.debug('* branch')
2933
const inputBranch = getInput('branch-name')
30-
if (inputBranch && inputBranch !== branch) {
31-
await switchBranch(inputBranch)
32-
await pushCurrentBranch()
33-
}
34+
const selectedBranch = inputBranch ? inputBranch : branch
35+
36+
core.debug('* owner')
37+
const inputOwner = getInput('owner')
38+
const selectedOwner = inputOwner ? inputOwner : owner
39+
40+
core.debug('* repo')
41+
const inputRepo = getInput('repo')
42+
const selectedRepo = inputRepo ? inputRepo : repo
3443

35-
const repositoryParts = inputRepository ? inputRepository.split('/') : []
36-
if (repositoryParts.length && repositoryParts.length != 2) {
37-
throw new InputRepositoryInvalid(inputRepository)
44+
if (
45+
selectedOwner == owner &&
46+
selectedRepo == repo &&
47+
selectedBranch !== branch
48+
) {
49+
core.warning(
50+
'Pushing local and current branch to remote before proceeding'
51+
)
52+
// Git commands
53+
await switchBranch(selectedBranch)
54+
await pushCurrentBranch()
3855
}
3956

40-
const currentOwner = repositoryParts.length ? repositoryParts[0] : owner
41-
const currentRepository = repositoryParts.length ? repositoryParts[1] : repo
42-
const currentBranch = inputBranch ? inputBranch : branch
4357
const repository = await core.group(
44-
`fetching repository info for owner: ${currentOwner}, repo: ${currentRepository}, branch: ${currentBranch}`,
58+
`fetching repository info for owner: ${selectedOwner}, repo: ${selectedRepo}, branch: ${selectedBranch}`,
4559
async () => {
4660
const startTime = Date.now()
4761
const repositoryData = await getRepository(
48-
currentOwner,
49-
currentRepository,
50-
currentBranch
62+
selectedOwner,
63+
selectedRepo,
64+
selectedBranch
5165
)
5266
const endTime = Date.now()
5367
core.debug(`time taken: ${(endTime - startTime).toString()} ms`)
5468
return repositoryData
5569
}
5670
)
5771

72+
core.info('Checking remote branches')
5873
if (!repository.ref) {
59-
if (inputBranch && currentBranch == inputBranch) {
74+
if (inputBranch) {
6075
throw new InputBranchNotFound(inputBranch)
6176
} else {
62-
throw new BranchNotFound(currentBranch)
77+
throw new BranchNotFound(branch)
6378
}
6479
}
6580

81+
core.info('Processing to create signed commit')
82+
core.debug('Get last (current?) commit')
6683
const currentCommit = repository.ref.target.history?.nodes?.[0]
6784
if (!currentCommit) {
6885
throw new BranchCommitNotFound(repository.ref.name)
@@ -71,12 +88,19 @@ export async function run(): Promise<void> {
7188
let createdCommit: Commit | undefined
7289
const filePaths = core.getMultilineInput('files')
7390
if (filePaths.length <= 0) {
74-
core.debug('skip file commit, empty files input')
91+
core.notice('skip file commit, empty files input')
7592
} else {
7693
core.debug(
77-
`proceed with file commit, input: ${JSON.stringify(filePaths)}`
94+
`Proceed with file commit, input: ${JSON.stringify(filePaths)}`
7895
)
7996

97+
const workdir = getWorkdir()
98+
const cwd = getCwd()
99+
if (cwd !== workdir) {
100+
core.notice('Changing working directory to Workdir: ' + workdir)
101+
process.chdir(workdir)
102+
}
103+
80104
await addFileChanges(filePaths)
81105
const fileChanges = await getFileChanges()
82106
const fileCount =
@@ -103,7 +127,7 @@ export async function run(): Promise<void> {
103127
commitMessage,
104128
{
105129
repositoryNameWithOwner: repository.nameWithOwner,
106-
branchName: currentBranch,
130+
branchName: selectedBranch,
107131
},
108132
fileChanges
109133
)

src/utils/cwd.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,11 @@ export function getWorkspace() {
1414
core.debug(`workspace: ${workspace}`)
1515
return workspace
1616
}
17+
18+
export function getWorkdir() {
19+
const workdir = getInput('workdir', {
20+
default: process.env.GITHUB_WORKSPACE,
21+
})
22+
core.debug(`workdir: ${workdir}`)
23+
return workdir
24+
}

0 commit comments

Comments
 (0)