Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions __test__/working-directory.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as fs from 'fs'
import * as os from 'os'
import * as path from 'path'
import {validateWorkingDirectory} from '../src/working-directory'

describe('validateWorkingDirectory', () => {
let tmpDir: string

beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'github-script-test-'))
})

afterEach(() => {
fs.rmSync(tmpDir, {recursive: true, force: true})
})

test('returns resolved path for existing directory', () => {
const result = validateWorkingDirectory(tmpDir)
expect(result).toBe(tmpDir)
})

test('resolves relative paths', () => {
const result = validateWorkingDirectory(tmpDir)
expect(path.isAbsolute(result)).toBe(true)
})

test('throws for non-existent directory', () => {
const nonExistent = path.join(tmpDir, 'does-not-exist')
expect(() => validateWorkingDirectory(nonExistent)).toThrow(
/does not exist/
)
expect(() => validateWorkingDirectory(nonExistent)).toThrow(nonExistent)
})

test('throws for file path instead of directory', () => {
const filePath = path.join(tmpDir, 'file.txt')
fs.writeFileSync(filePath, 'content')
expect(() => validateWorkingDirectory(filePath)).toThrow(
/is not a directory/
)
expect(() => validateWorkingDirectory(filePath)).toThrow(filePath)
})
})
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ inputs:
base-url:
description: An optional GitHub REST API URL to connect to a different GitHub instance. For example, https://my.github-enterprise-server.com/api/v3
required: false
working-directory:
description: The working directory where the script will be executed. If not provided, the current working directory is used.
required: false
outputs:
result:
description: The return value of the script, stringified with `JSON.stringify`
Expand Down
28 changes: 28 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65029,6 +65029,27 @@ function parseNumberArray(listString) {

// EXTERNAL MODULE: external "path"
var external_path_ = __nccwpck_require__(1017);
;// CONCATENATED MODULE: ./src/working-directory.ts


/**
* Validates that the given directory exists and is accessible.
* @param workingDirectory - The directory path to validate
* @returns The resolved absolute path
* @throws Error if the directory does not exist or is not a directory
*/
function validateWorkingDirectory(workingDirectory) {
const resolved = external_path_.resolve(workingDirectory);
if (!external_fs_.existsSync(resolved)) {
throw new Error(`working-directory "${workingDirectory}" does not exist (resolved to "${resolved}")`);
}
const stat = external_fs_.statSync(resolved);
if (!stat.isDirectory()) {
throw new Error(`working-directory "${workingDirectory}" is not a directory (resolved to "${resolved}")`);
}
return resolved;
}

;// CONCATENATED MODULE: ./src/wrap-require.ts

const wrapRequire = new Proxy(require, {
Expand Down Expand Up @@ -65065,6 +65086,7 @@ const wrapRequire = new Proxy(require, {




process.on('unhandledRejection', handleError);
main().catch(handleError);
async function main() {
Expand Down Expand Up @@ -65092,6 +65114,12 @@ async function main() {
}
const github = getOctokit(token, opts, retry, requestLog);
const script = core.getInput('script', { required: true });
const workingDirectory = core.getInput('working-directory');
if (workingDirectory) {
const resolved = validateWorkingDirectory(workingDirectory);
core.info(`Changing working directory to ${resolved}`);
process.chdir(resolved);
}
// Wrap getOctokit so secondary clients inherit retry, logging,
// orchestration ID, and the action's retries input.
// Deep-copy opts to prevent shared references with the primary client.
Expand Down
8 changes: 8 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {RequestRequestOptions} from '@octokit/types'
import {callAsyncFunction} from './async-function'
import {createConfiguredGetOctokit} from './create-configured-getoctokit'
import {RetryOptions, getRetryOptions, parseNumberArray} from './retry-options'
import {validateWorkingDirectory} from './working-directory'
import {wrapRequire} from './wrap-require'

process.on('unhandledRejection', handleError)
Expand Down Expand Up @@ -59,6 +60,13 @@ async function main(): Promise<void> {

const github = getOctokit(token, opts, retry, requestLog)
const script = core.getInput('script', {required: true})
const workingDirectory = core.getInput('working-directory')

if (workingDirectory) {
const resolved = validateWorkingDirectory(workingDirectory)
core.info(`Changing working directory to ${resolved}`)
process.chdir(resolved)
}

// Wrap getOctokit so secondary clients inherit retry, logging,
// orchestration ID, and the action's retries input.
Expand Down
27 changes: 27 additions & 0 deletions src/working-directory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as fs from 'fs'
import * as path from 'path'

/**
* Validates that the given directory exists and is accessible.
* @param workingDirectory - The directory path to validate
* @returns The resolved absolute path
* @throws Error if the directory does not exist or is not a directory
*/
export function validateWorkingDirectory(workingDirectory: string): string {
const resolved = path.resolve(workingDirectory)

if (!fs.existsSync(resolved)) {
throw new Error(
`working-directory "${workingDirectory}" does not exist (resolved to "${resolved}")`
)
}

const stat = fs.statSync(resolved)
if (!stat.isDirectory()) {
throw new Error(
`working-directory "${workingDirectory}" is not a directory (resolved to "${resolved}")`
)
}

return resolved
}