From ec00d65c65bf19020f5b6b1a359605d5ebe9f61f Mon Sep 17 00:00:00 2001 From: Daniel Hwang Date: Fri, 29 May 2020 15:57:30 -0700 Subject: [PATCH] add support for gist.github.com --- README.md | 3 +++ __test__/git-auth-helper.test.ts | 1 + __test__/input-helper.test.ts | 7 +++++++ action.yml | 2 ++ dist/index.js | 32 ++++++++++++++++++++++++-------- src/git-auth-helper.ts | 2 +- src/git-source-settings.ts | 5 +++++ src/input-helper.ts | 12 ++++++++++-- src/url-helper.ts | 21 ++++++++++++++++----- 9 files changed, 69 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 9104f8b..8982c3f 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,9 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous # Default: ${{ github.repository }} repository: '' + # Gist name with owner. For example, schacon/1 + gist: '' + # The branch, tag or SHA to checkout. When checking out the repository that # triggered a workflow, this defaults to the reference or SHA for that event. # Otherwise, defaults to `master`. diff --git a/__test__/git-auth-helper.test.ts b/__test__/git-auth-helper.test.ts index 92a462a..ce7b914 100644 --- a/__test__/git-auth-helper.test.ts +++ b/__test__/git-auth-helper.test.ts @@ -767,6 +767,7 @@ async function setup(testName: string): Promise { repositoryName: 'my-repo', repositoryOwner: 'my-org', repositoryPath: '', + isGist: false, sshKey: sshPath ? 'some ssh private key' : '', sshKnownHosts: '', sshStrict: true diff --git a/__test__/input-helper.test.ts b/__test__/input-helper.test.ts index 00732ef..0a59969 100644 --- a/__test__/input-helper.test.ts +++ b/__test__/input-helper.test.ts @@ -117,6 +117,13 @@ describe('input-helper tests', () => { expect(settings.commit).toBeFalsy() }) + it('sets correct default ref/sha for gist', () => { + inputs.gist = 'some-owner/some-gist' + const settings: IGitSourceSettings = inputHelper.getInputs() + expect(settings.ref).toBe('refs/heads/master') + expect(settings.commit).toBeFalsy() + }) + it('sets ref to empty when explicit sha', () => { inputs.ref = '1111111111222222222233333333334444444444' const settings: IGitSourceSettings = inputHelper.getInputs() diff --git a/action.yml b/action.yml index 58e11b7..c066833 100644 --- a/action.yml +++ b/action.yml @@ -4,6 +4,8 @@ inputs: repository: description: 'Repository name with owner. For example, actions/checkout' default: ${{ github.repository }} + gist: + description: 'Gist name with owner. For example, schacon/1' ref: description: > The branch, tag or SHA to checkout. When checking out the repository that diff --git a/dist/index.js b/dist/index.js index 0c78d25..3312562 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1389,21 +1389,30 @@ const url_1 = __webpack_require__(835); function getFetchUrl(settings) { assert.ok(settings.repositoryOwner, 'settings.repositoryOwner must be defined'); assert.ok(settings.repositoryName, 'settings.repositoryName must be defined'); - const serviceUrl = getServerUrl(); + const serviceUrl = getServerUrl(settings.isGist); const encodedOwner = encodeURIComponent(settings.repositoryOwner); const encodedName = encodeURIComponent(settings.repositoryName); + let encodedNwo = `${encodedOwner}/${encodedName}`; + if (settings.isGist) { + encodedNwo = encodedName; + } if (settings.sshKey) { - return `git@${serviceUrl.hostname}:${encodedOwner}/${encodedName}.git`; + return `git@${serviceUrl.hostname}:${encodedNwo}.git`; } // "origin" is SCHEME://HOSTNAME[:PORT] - return `${serviceUrl.origin}/${encodedOwner}/${encodedName}`; + return `${serviceUrl.origin}/${encodedNwo}`; } exports.getFetchUrl = getFetchUrl; -function getServerUrl() { +function getServerUrl(isGist) { // todo: remove GITHUB_URL after support for GHES Alpha is no longer needed - return new url_1.URL(process.env['GITHUB_SERVER_URL'] || + let serverUrl = new url_1.URL(process.env['GITHUB_SERVER_URL'] || process.env['GITHUB_URL'] || 'https://github.com'); + // todo: don't assume subdomain isolation + if (isGist) { + serverUrl.hostname = `gist.${serverUrl.hostname}`; + } + return serverUrl; } exports.getServerUrl = getServerUrl; @@ -5418,7 +5427,7 @@ class GitAuthHelper { this.git = gitCommandManager; this.settings = gitSourceSettings || {}; // Token auth header - const serverUrl = urlHelper.getServerUrl(); + const serverUrl = urlHelper.getServerUrl(this.settings.isGist); this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader`; // "origin" is SCHEME://HOSTNAME[:PORT] const basicCredential = Buffer.from(`x-access-token:${this.settings.authToken}`, 'utf8').toString('base64'); core.setSecret(basicCredential); @@ -14438,15 +14447,22 @@ function getInputs() { githubWorkspacePath = path.resolve(githubWorkspacePath); core.debug(`GITHUB_WORKSPACE = '${githubWorkspacePath}'`); fsHelper.directoryExistsSync(githubWorkspacePath, true); + // Gist repository? + result.isGist = !!core.getInput('gist') || false; + core.debug(`isGist = '${result.isGist}'`); // Qualified repository - const qualifiedRepository = core.getInput('repository') || + let qualifiedRepository = core.getInput('repository') || `${github.context.repo.owner}/${github.context.repo.repo}`; + if (result.isGist) { + qualifiedRepository = core.getInput('gist'); + } core.debug(`qualified repository = '${qualifiedRepository}'`); const splitRepository = qualifiedRepository.split('/'); if (splitRepository.length !== 2 || !splitRepository[0] || !splitRepository[1]) { - throw new Error(`Invalid repository '${qualifiedRepository}'. Expected format {owner}/{repo}.`); + const model = result.isGist ? 'gist' : 'repository'; + throw new Error(`Invalid ${model} '${qualifiedRepository}'. Expected format {owner}/{repo}.`); } result.repositoryOwner = splitRepository[0]; result.repositoryName = splitRepository[1]; diff --git a/src/git-auth-helper.ts b/src/git-auth-helper.ts index fc1404c..46330fe 100644 --- a/src/git-auth-helper.ts +++ b/src/git-auth-helper.ts @@ -51,7 +51,7 @@ class GitAuthHelper { this.settings = gitSourceSettings || (({} as unknown) as IGitSourceSettings) // Token auth header - const serverUrl = urlHelper.getServerUrl() + const serverUrl = urlHelper.getServerUrl(this.settings.isGist) this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader` // "origin" is SCHEME://HOSTNAME[:PORT] const basicCredential = Buffer.from( `x-access-token:${this.settings.authToken}`, diff --git a/src/git-source-settings.ts b/src/git-source-settings.ts index 2786222..2d26ba2 100644 --- a/src/git-source-settings.ts +++ b/src/git-source-settings.ts @@ -73,4 +73,9 @@ export interface IGitSourceSettings { * Indicates whether to persist the credentials on disk to enable scripting authenticated git commands */ persistCredentials: boolean + + /** + * Indicates whether this repository is a gist + */ + isGist: boolean } diff --git a/src/input-helper.ts b/src/input-helper.ts index 11a1ab6..a692cf3 100644 --- a/src/input-helper.ts +++ b/src/input-helper.ts @@ -16,10 +16,17 @@ export function getInputs(): IGitSourceSettings { core.debug(`GITHUB_WORKSPACE = '${githubWorkspacePath}'`) fsHelper.directoryExistsSync(githubWorkspacePath, true) + // Gist repository? + result.isGist = !!core.getInput('gist') || false + core.debug(`isGist = '${result.isGist}'`) + // Qualified repository - const qualifiedRepository = + let qualifiedRepository = core.getInput('repository') || `${github.context.repo.owner}/${github.context.repo.repo}` + if (result.isGist) { + qualifiedRepository = core.getInput('gist') + } core.debug(`qualified repository = '${qualifiedRepository}'`) const splitRepository = qualifiedRepository.split('/') if ( @@ -27,8 +34,9 @@ export function getInputs(): IGitSourceSettings { !splitRepository[0] || !splitRepository[1] ) { + const model = result.isGist ? 'gist' : 'repository' throw new Error( - `Invalid repository '${qualifiedRepository}'. Expected format {owner}/{repo}.` + `Invalid ${model} '${qualifiedRepository}'. Expected format {owner}/{repo}.` ) } result.repositoryOwner = splitRepository[0] diff --git a/src/url-helper.ts b/src/url-helper.ts index 05f1cbd..6c2a6de 100644 --- a/src/url-helper.ts +++ b/src/url-helper.ts @@ -8,22 +8,33 @@ export function getFetchUrl(settings: IGitSourceSettings): string { 'settings.repositoryOwner must be defined' ) assert.ok(settings.repositoryName, 'settings.repositoryName must be defined') - const serviceUrl = getServerUrl() + const serviceUrl = getServerUrl(settings.isGist) const encodedOwner = encodeURIComponent(settings.repositoryOwner) const encodedName = encodeURIComponent(settings.repositoryName) + let encodedNwo = `${encodedOwner}/${encodedName}` + if (settings.isGist) { + encodedNwo = encodedName + } if (settings.sshKey) { - return `git@${serviceUrl.hostname}:${encodedOwner}/${encodedName}.git` + return `git@${serviceUrl.hostname}:${encodedNwo}.git` } // "origin" is SCHEME://HOSTNAME[:PORT] - return `${serviceUrl.origin}/${encodedOwner}/${encodedName}` + return `${serviceUrl.origin}/${encodedNwo}` } -export function getServerUrl(): URL { +export function getServerUrl(isGist: boolean): URL { // todo: remove GITHUB_URL after support for GHES Alpha is no longer needed - return new URL( + let serverUrl = new URL( process.env['GITHUB_SERVER_URL'] || process.env['GITHUB_URL'] || 'https://github.com' ) + + // todo: don't assume subdomain isolation + if (isGist) { + serverUrl.hostname = `gist.${serverUrl.hostname}` + } + + return serverUrl }