use token for workflow repo

This commit is contained in:
eric sciple 2020-03-18 23:33:26 -04:00
parent 9a3a9ade82
commit 85a425b582
8 changed files with 210 additions and 47 deletions

View file

@ -33,6 +33,7 @@ export interface IGitCommandManager {
remoteAdd(remoteName: string, remoteUrl: string): Promise<void>
removeEnvironmentVariable(name: string): void
setEnvironmentVariable(name: string, value: string): void
setRemoteUrl(url: string): Promise<void>
submoduleForeach(command: string, recursive: boolean): Promise<string>
submoduleSync(recursive: boolean): Promise<void>
submoduleUpdate(fetchDepth: number, recursive: boolean): Promise<void>
@ -40,7 +41,7 @@ export interface IGitCommandManager {
tryClean(): Promise<boolean>
tryConfigUnset(configKey: string, globalConfig?: boolean): Promise<boolean>
tryDisableAutomaticGarbageCollection(): Promise<boolean>
tryGetFetchUrl(): Promise<string>
tryGetRemoteUrl(): Promise<string>
tryReset(): Promise<boolean>
}
@ -241,6 +242,10 @@ class GitCommandManager {
this.gitEnv[name] = value
}
async setRemoteUrl(value: string): Promise<void> {
await this.config('git.remote.url', value)
}
async submoduleForeach(command: string, recursive: boolean): Promise<string> {
const args = ['submodule', 'foreach']
if (recursive) {
@ -309,7 +314,7 @@ class GitCommandManager {
return output.exitCode === 0
}
async tryGetFetchUrl(): Promise<string> {
async tryGetRemoteUrl(): Promise<string> {
const output = await this.execGit(
['config', '--local', '--get', 'remote.origin.url'],
true

View file

@ -1,18 +1,30 @@
import * as assert from 'assert'
import * as core from '@actions/core'
import * as fs from 'fs'
import * as fsHelper from './fs-helper'
import * as io from '@actions/io'
import * as path from 'path'
import {IGitCommandManager} from './git-command-manager'
import {IGitSourceSettings} from './git-source-settings'
export async function prepareExistingDirectory(
git: IGitCommandManager | undefined,
repositoryPath: string,
repositoryUrl: string,
preferredRemoteUrl: string,
allowedRemoteUrls: string[],
clean: boolean
): Promise<void> {
assert.ok(repositoryPath, 'Expected repositoryPath to be defined')
assert.ok(preferredRemoteUrl, 'Expected preferredRemoteUrl to be defined')
assert.ok(allowedRemoteUrls, 'Expected allowedRemoteUrls to be defined')
assert.ok(allowedRemoteUrls.length, 'Expected allowedRemoteUrls to have at least one value')
// Indicates whether to delete the directory contents
let remove = false
// The remote URL
let remoteUrl: string
// Check whether using git or REST API
if (!git) {
remove = true
@ -20,7 +32,7 @@ export async function prepareExistingDirectory(
// Fetch URL does not match
else if (
!fsHelper.directoryExistsSync(path.join(repositoryPath, '.git')) ||
repositoryUrl !== (await git.tryGetFetchUrl())
allowedRemoteUrls.indexOf((remoteUrl = await git.tryGetRemoteUrl())) < 0
) {
remove = true
} else {
@ -72,6 +84,11 @@ export async function prepareExistingDirectory(
)
}
}
// Update to the preferred remote URL
if (remoteUrl !== preferredRemoteUrl) {
await git.setRemoteUrl(preferredRemoteUrl)
}
} catch (error) {
core.warning(
`Unable to prepare the existing repository. The repository will be recreated instead.`

View file

@ -14,17 +14,21 @@ import {IGitSourceSettings} from './git-source-settings'
const hostname = 'github.com'
export async function getSource(settings: IGitSourceSettings): Promise<void> {
// Repository URL
core.info(
`Syncing repository: ${settings.repositoryOwner}/${settings.repositoryName}`
)
const repositoryUrl = settings.sshKey
? `git@${hostname}:${encodeURIComponent(
settings.repositoryOwner
)}/${encodeURIComponent(settings.repositoryName)}.git`
: `https://${hostname}/${encodeURIComponent(
settings.repositoryOwner
)}/${encodeURIComponent(settings.repositoryName)}`
// Remote URL
const httpsUrl = `https://${hostname}/${encodeURIComponent(
settings.repositoryOwner
)}/${encodeURIComponent(settings.repositoryName)}`
const sshUrl = `git@${hostname}:${encodeURIComponent(
settings.repositoryOwner
)}/${encodeURIComponent(settings.repositoryName)}.git`
// Always fetch the workflow repository using the token, not the SSH key
const initialRemoteUrl =
!settings.sshKey || settings.isWorkflowRepository ? httpsUrl : sshUrl
// Remove conflicting file path
if (fsHelper.fileExistsSync(settings.repositoryPath)) {
@ -46,7 +50,8 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
await gitDirectoryHelper.prepareExistingDirectory(
git,
settings.repositoryPath,
repositoryUrl,
initialRemoteUrl,
[httpsUrl, sshUrl],
settings.clean
)
}
@ -86,7 +91,7 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
!fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git'))
) {
await git.init()
await git.remoteAdd('origin', repositoryUrl)
await git.remoteAdd('origin', initialRemoteUrl)
}
// Disable automatic garbage collection
@ -124,6 +129,11 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
await git.lfsFetch(checkoutInfo.startPoint || checkoutInfo.ref)
}
// Fix URL when using SSH
if (settings.sshKey && initialRemoteUrl != sshUrl) {
await git.setRemoteUrl(sshUrl)
}
// Checkout
await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint)

View file

@ -1,17 +1,81 @@
export interface IGitSourceSettings {
/**
* The location on disk where the repository will be placed
*/
repositoryPath: string
/**
* The repository owner
*/
repositoryOwner: string
/**
* The repository name
*/
repositoryName: string
/**
* Indicates whether the repository is main workflow repository
*/
isWorkflowRepository: boolean
/**
* The ref to fetch
*/
ref: string
/**
* The commit to checkout
*/
commit: string
/**
* Indicates whether to clean the repository
*/
clean: boolean
/**
* The depth when fetching
*/
fetchDepth: number
/**
* Indicates whether to fetch LFS objects
*/
lfs: boolean
/**
* Indicates whether to checkout submodules
*/
submodules: boolean
/**
* Indicates whether to recursively checkout submodules
*/
nestedSubmodules: boolean
/**
* The auth token to use when fetching the repository
*/
authToken: string
/**
* The SSH key to configure
*/
sshKey: string
/**
* Additional SSH known hosts
*/
sshKnownHosts: string
/**
* Indicates whether the server must be a known host
*/
sshStrict: boolean
/**
* Indicates whether to persist the credentials on disk to enable scripting authenticated git commands
*/
persistCredentials: boolean
}

View file

@ -4,6 +4,8 @@ import * as github from '@actions/github'
import * as path from 'path'
import {IGitSourceSettings} from './git-source-settings'
const hostname = 'github.com'
export function getInputs(): IGitSourceSettings {
const result = ({} as unknown) as IGitSourceSettings
@ -51,14 +53,14 @@ export function getInputs(): IGitSourceSettings {
}
// Workflow repository?
const isWorkflowRepository =
result.isWorkflowRepository =
qualifiedRepository.toUpperCase() ===
`${github.context.repo.owner}/${github.context.repo.repo}`.toUpperCase()
// Source branch, source version
result.ref = core.getInput('ref')
if (!result.ref) {
if (isWorkflowRepository) {
if (result.isWorkflowRepository) {
result.ref = github.context.ref
result.commit = github.context.sha