Skip to content

Commit

Permalink
Merge pull request #1005 from garden-io/fix-git-url-validation
Browse files Browse the repository at this point in the history
fix(vcs): fixed support for GitHub SSH URLs and added tests
  • Loading branch information
eysi09 authored Jul 23, 2019
2 parents 7cab371 + 7b061ec commit c43490c
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 49 deletions.
6 changes: 3 additions & 3 deletions docs/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,9 @@ A key/value map of variables that modules can reference when using this environm

A list of environments to configure for the project.

| Type | Required |
| -------------- | -------- |
| `alternatives` | No |
| Type | Required |
| ------------------------------- | -------- |
| `array[object] | array[string]` | No |

Example:

Expand Down
55 changes: 33 additions & 22 deletions garden-service/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions garden-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"ignore": "^5.1.1",
"indent-string": "^4.0.0",
"inquirer": "^6.3.1",
"is-git-url": "^1.0.0",
"js-yaml": "^3.13.1",
"json-diff": "^0.5.4",
"json-merge-patch": "^0.2.3",
Expand Down Expand Up @@ -127,6 +128,7 @@
"@types/hapi__joi": "^15.0.2",
"@types/has-ansi": "^3.0.0",
"@types/inquirer": "6.0.1",
"@types/is-git-url": "^1.0.0",
"@types/js-yaml": "^3.12.1",
"@types/json-merge-patch": "0.0.4",
"@types/json-stringify-safe": "^5.0.0",
Expand Down
70 changes: 53 additions & 17 deletions garden-service/src/config/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import * as uuid from "uuid"
import { ConfigurationError, LocalConfigError } from "../exceptions"
import chalk from "chalk"
import { relative } from "path"
import { splitLast } from "../util/util"
import isGitUrl = require("is-git-url")

export type Primitive = string | number | boolean | null

Expand All @@ -26,6 +28,10 @@ export const enumToArray = Enum => (
Object.values(Enum).filter(k => typeof k === "string") as string[]
)

interface JoiGitUrlParams {
requireHash?: boolean
}

interface JoiPathParams {
absoluteOnly?: boolean
relativeOnly?: boolean
Expand All @@ -34,6 +40,7 @@ interface JoiPathParams {

// Extend the Joi module with our custom rules
export interface CustomStringSchema extends Joi.StringSchema {
gitUrl: (params: JoiGitUrlParams) => CustomStringSchema
posixPath: (params?: JoiPathParams) => CustomStringSchema
}

Expand All @@ -45,12 +52,48 @@ export const joi: Joi.Root = Joi.extend({
base: Joi.string(),
name: "string",
language: {
gitUrl: "must be a valid Git repository URL",
requireHash: "must specify a branch/tag hash",
posixPath: "must be a POSIX-style path", // Used below as 'string.posixPath'
absoluteOnly: "must be a an absolute path",
relativeOnly: "must be a relative path (may not be an absolute path)",
subPathOnly: "must be a relative sub-path (may not contain '..' or be an absolute path)",
},
rules: [
{
name: "gitUrl",
params: {
options: Joi.object()
.keys({
requireHash: Joi.boolean()
.description("Only allow Git URLs with a branch/tag hash."),
}),
},
validate(params: { options?: JoiGitUrlParams }, value: string, state, prefs) {
// Make sure it's a string
const baseSchema = Joi.string()
const result = baseSchema.validate(value)

if (result.error) {
return result.error
}

if (!isGitUrl(value)) {
// tslint:disable-next-line:no-invalid-this
return this.createError("string.gitUrl", { v: value }, state, prefs)
}

if (params.options && params.options.requireHash === true) {
const url = splitLast(value, "#")[0]
if (!url) {
// tslint:disable-next-line:no-invalid-this
return this.createError("string.requireHash", { v: value }, state, prefs)
}
}

return value
},
},
{
name: "posixPath",
params: {
Expand Down Expand Up @@ -127,7 +170,7 @@ export const joiProviderName = (name: string) => joiIdentifier().required()
.default(name)
.example(name)

export const joiStringMap = (valueSchema: JoiObject) => Joi
export const joiStringMap = (valueSchema: JoiObject) => joi
.object().pattern(/.+/, valueSchema)

export const joiUserIdentifier = () => joi.string()
Expand All @@ -138,18 +181,18 @@ export const joiUserIdentifier = () => joi.string()
"or be longer than 63 characters.",
)

export const joiIdentifierMap = (valueSchema: JoiObject) => Joi
export const joiIdentifierMap = (valueSchema: JoiObject) => joi
.object().pattern(identifierRegex, valueSchema)
.default(() => ({}), "{}")
.description("Key/value map. Keys must be valid identifiers.")

export const joiVariables = () => Joi
export const joiVariables = () => joi
.object().pattern(/[\w\d]+/i, joiPrimitive())
.default(() => ({}), "{}")
.unknown(false)
.description("Key/value map. Keys may contain letters and numbers, and values must be primitives.")

export const joiEnvVars = () => Joi
export const joiEnvVars = () => joi
.object().pattern(envVarRegex, joiPrimitive())
.default(() => ({}), "{}")
.unknown(false)
Expand All @@ -158,22 +201,15 @@ export const joiEnvVars = () => Joi
"(must not start with `GARDEN`) and values must be primitives.",
)

export const joiArray = (schema) => Joi
export const joiArray = (schema) => joi
.array().items(schema)
.default(() => [], "[]")

export const joiRepositoryUrl = () => Joi
.string()
.uri({
scheme: [
"git",
/git\+https?/,
/git\+ssh?/,
"https",
"file",
"ssh",
],
})
export const joiRepositoryUrl = () => joi.alternatives(
joi.string().gitUrl({ requireHash: true }),
// Allow file URLs as well
joi.string().uri({ scheme: ["file"] }),
)
.description(
"A remote repository URL. Currently only supports git servers. Must contain a hash suffix" +
" pointing to a specific branch or tag, with the format: <git remote url>#<branch|tag>",
Expand Down
Loading

0 comments on commit c43490c

Please sign in to comment.