Feat: add support for absolute paths (#449)

* Feat: add support for absolute paths

* Refactor: `generateFolderPath` to generic function

`action.root` is initialized at e42fda2d72/src/constants.ts (L98), so it should not be an optional property.

* Test: rm unnecessary tests

* Refactor: rm unused exports
This commit is contained in:
Exuanbo 2020-10-07 14:34:20 +01:00 committed by GitHub
parent b96b1d043d
commit 118cd3f75b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 60 deletions

View File

@ -178,51 +178,6 @@ describe('git', () => {
}
})
it('should fail if the build folder begins with a /', async () => {
Object.assign(action, {
silent: false,
accessToken: '123',
repositoryPath: 'JamesIves/github-pages-deploy-action',
branch: 'branch',
folder: '/',
pusher: {
name: 'asd',
email: 'as@cat'
}
})
try {
await init(action)
} catch (e) {
expect(execute).toBeCalledTimes(0)
expect(e.message).toMatch(
"There was an error initializing the repository: Incorrectly formatted build folder. The deployment folder cannot be prefixed with '/' or './'. Instead reference the folder name directly. ❌"
)
}
})
it('should fail if the build folder begins with a ./', async () => {
Object.assign(action, {
silent: false,
accessToken: '123',
branch: 'branch',
folder: './',
pusher: {
name: 'asd',
email: 'as@cat'
}
})
try {
await init(action)
} catch (e) {
expect(execute).toBeCalledTimes(0)
expect(e.message).toMatch(
"There was an error initializing the repository: Incorrectly formatted build folder. The deployment folder cannot be prefixed with '/' or './'. Instead reference the folder name directly. ❌"
)
}
})
it('should not fail if root is used', async () => {
Object.assign(action, {
silent: false,

View File

@ -2,6 +2,7 @@ import {
isNullOrUndefined,
generateTokenType,
generateRepositoryPath,
generateFolderPath,
suppressSensitiveInformation
} from '../src/util'
@ -177,4 +178,67 @@ describe('util', () => {
})
})
})
describe('generateFolderPath', () => {
it('should return absolute path if folder name is provided', () => {
const action = {
branch: '123',
root: '.',
workspace: 'src/',
folder: 'build',
gitHubToken: null,
accessToken: null,
ssh: null,
silent: false
}
expect(generateFolderPath(action, 'folder')).toEqual('src/build')
})
it('should return original path if folder name begins with /', () => {
const action = {
branch: '123',
root: '.',
workspace: 'src/',
folder: '/home/user/repo/build',
gitHubToken: null,
accessToken: null,
ssh: null,
silent: false
}
expect(generateFolderPath(action, 'folder')).toEqual(
'/home/user/repo/build'
)
})
it('should process as relative path if folder name begins with ./', () => {
const action = {
branch: '123',
root: '.',
workspace: 'src/',
folder: './build',
gitHubToken: null,
accessToken: null,
ssh: null,
silent: false
}
expect(generateFolderPath(action, 'folder')).toEqual('src/build')
})
it('should return absolute path if folder name begins with ~', () => {
const action = {
branch: '123',
root: '.',
workspace: 'src/',
folder: '~/repo/build',
gitHubToken: null,
accessToken: null,
ssh: null,
silent: false
}
process.env.HOME = '/home/user'
expect(generateFolderPath(action, 'folder')).toEqual(
'/home/user/repo/build'
)
})
})
})

View File

@ -39,7 +39,7 @@ export interface ActionInterface {
/** The fully qualified repositpory path, this gets auto generated if repositoryName is provided. */
repositoryPath?: string
/** The root directory where your project lives. */
root?: string
root: string
/** Wipes the commit history from the deployment branch in favor of a single commit. */
singleCommit?: boolean | null
/** Determines if the action should run in silent mode or not. */
@ -109,6 +109,10 @@ export const action: ActionInterface = {
workspace: process.env.GITHUB_WORKSPACE || ''
}
export type ActionFolders = NonNullable<
Pick<ActionInterface, 'folder' | 'root'>
>
/** Status codes for the action. */
export enum Status {
SUCCESS = 'success',

View File

@ -4,6 +4,7 @@ import fs from 'fs'
import {ActionInterface, Status} from './constants'
import {execute} from './execute'
import {
generateFolderPath,
hasRequiredParameters,
isNullOrUndefined,
suppressSensitiveInformation
@ -130,6 +131,8 @@ export async function generateBranch(action: ActionInterface): Promise<void> {
/* Runs the necessary steps to make the deployment. */
export async function deploy(action: ActionInterface): Promise<Status> {
const folderPath = generateFolderPath(action, 'folder')
const rootPath = generateFolderPath(action, 'root')
const temporaryDeploymentDirectory =
'github-pages-deploy-action-temp-deployment-folder'
const temporaryDeploymentBranch = `github-pages-deploy-action/${Math.random()
@ -229,22 +232,22 @@ export async function deploy(action: ActionInterface): Promise<Status> {
Allows the user to specify the root if '.' is provided.
rsync is used to prevent file duplication. */
await execute(
`rsync -q -av --checksum --progress ${action.folder}/. ${
`rsync -q -av --checksum --progress ${folderPath}/. ${
action.targetFolder
? `${temporaryDeploymentDirectory}/${action.targetFolder}`
: temporaryDeploymentDirectory
} ${
action.clean
? `--delete ${excludes} ${
!fs.existsSync(`${action.folder}/CNAME`) ? '--exclude CNAME' : ''
!fs.existsSync(`${folderPath}/CNAME`) ? '--exclude CNAME' : ''
} ${
!fs.existsSync(`${action.folder}/.nojekyll`)
!fs.existsSync(`${folderPath}/.nojekyll`)
? '--exclude .nojekyll'
: ''
}`
: ''
} --exclude .ssh --exclude .git --exclude .github ${
action.folder === action.root
folderPath === rootPath
? `--exclude ${temporaryDeploymentDirectory}`
: ''
}`,

View File

@ -1,6 +1,6 @@
import {exportVariable, info, setFailed} from '@actions/core'
import {action, ActionInterface, Status} from './constants'
import {deploy, generateBranch, init} from './git'
import {deploy, init} from './git'
import {generateRepositoryPath, generateTokenType} from './util'
/** Initializes and runs the action.
@ -53,5 +53,3 @@ export default async function run(
exportVariable('DEPLOYMENT_STATUS', status)
}
}
export {init, deploy, generateBranch, ActionInterface}

View File

@ -1,5 +1,6 @@
import path from 'path'
import {isDebug} from '@actions/core'
import {ActionInterface} from './constants'
import {ActionInterface, ActionFolders} from './constants'
const replaceAll = (input: string, find: string, replace: string): string =>
input.split(find).join(replace)
@ -26,6 +27,20 @@ export const generateRepositoryPath = (action: ActionInterface): string =>
action.accessToken || `x-access-token:${action.gitHubToken}`
}@github.com/${action.repositoryName}.git`
/* Genetate absolute folder path by the provided folder name */
export const generateFolderPath = <K extends keyof ActionFolders>(
action: ActionInterface,
key: K
): string => {
const folderName = action[key]
const folderPath = path.isAbsolute(folderName)
? folderName
: folderName.startsWith('~')
? folderName.replace('~', process.env.HOME as string)
: path.join(action.workspace, folderName)
return folderPath
}
/* Checks for the required tokens and formatting. Throws an error if any case is matched. */
export const hasRequiredParameters = (action: ActionInterface): void => {
if (
@ -47,12 +62,6 @@ export const hasRequiredParameters = (action: ActionInterface): void => {
if (!action.folder || isNullOrUndefined(action.folder)) {
throw new Error('You must provide the action with a folder to deploy.')
}
if (action.folder.startsWith('/') || action.folder.startsWith('./')) {
throw new Error(
"Incorrectly formatted build folder. The deployment folder cannot be prefixed with '/' or './'. Instead reference the folder name directly."
)
}
}
/* Suppresses sensitive information from being exposed in error messages. */