.gitlab-ci.yml schema broken for job:secrets
Summary
Schema for .gitlab-ci.yml disagrees with documentation (web reference, also code), CI lint and actual pipeline instances.
The schema is defined so that it expects an additional layer between job:secrets and its descendant vault and mistakenly reports for working usages one of
- "Schema validation: Incompatible types. Required: object. Actual: string." - for "vault" with value of type string, or
- "Schema validation: Missing required property 'vault'" - for "vault" with value of type object.
The code author agrees this is an oversight.
(Code and the bug were transferred from JSON Schema Store to GitLab in late September.)
Steps to reproduce
- From the documentation take the first example code for
secrets, put it into.gitlab-ci.ymland add ascriptconfig (to satisfy the schema otherwise):
job:
secrets:
DATABASE_PASSWORD: # Store the path to the secret in this CI/CD variable
vault: # Translates to secret: `ops/data/production/db`, field: `password`
engine:
name: kv-v2
path: ops
path: production/db
field: password
script:
echo "foo"
- Have a syntax validator using the current schema, e. g. IntelliJ (mine still uses the schema from JSON Schema Store which is materially the same as the local one). Note, GitLab's CI lint does not use the schema.
- old schema URL: https://json.schemastore.org/gitlab-ci
- new schema URL: https://gitlab.com/gitlab-org/gitlab/-/raw/master/app/assets/javascripts/editor/schema/ci.json
- Validate syntax and get "Schema validation: Missing required property 'vault'"
Example Project
Basically only a .gitlab-ci.yml - gitlab-ci-secrets-schema.
What is the current bug behavior?
Syntax validator (IntelliJ) issues warnings about syntactically correct secrets configurations in .gitlab-ci.yml.
What is the expected correct behavior?
Syntax should be correctly validated.
Relevant logs and/or screenshots
Here is the problematic code. Note, there are two layers "additionalProperties" (each of type object) between "secrets" and "vault" with only the inner layer requiring a key "vault".
"secrets": {
"type": "object",
"additionalProperties": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"vault": {
"oneOf": [
{
"type": "string",
},
{
"type": "object",
}
]
}
},
"required": ["vault"]
This disallows
-
secrets:<name>:vault:<string-type-value>because the inner "additionalProperties" needs to be of type object. -
secrets:<name>:vault:<object-without-key-vault>because the inner "additionalProperties" needs a key "vault".
Here are examples (same as in the project linked above) with the two allowed types for the value of "vault" each in a format where either CI lint or the schema validator disagrees and with the stated disagreement.
# job-1: No extra layer, "vault" with value of type object
# Schema disagrees, CI linter agrees
# Warning: "Schema validation: Missing required property 'vault'"
job-1:
secrets:
DATA_FILE:
vault:
engine:
name: kv-v2
path: ops
path: production/db
field: some_data
script:
cat $DATA_FILE
# job-2: With extra layer "some_name", "vault" with value of type object
# Schema agrees, CI linter disagrees
# Warnings:
# - "jobs:job-2:secrets:data_file config contains unknown keys: some_name"
# - "jobs:job-2:secrets:data_file config missing required keys: vault"
job-2:
secrets:
DATA_FILE:
some_name:
vault:
engine:
name: kv-v2
path: ops
path: production/db
field: some_data
script:
cat $DATA_FILE
# job-3: No extra layer, "vault" with value of type string
# Schema disagrees, CI linter agrees
# Warning: "Schema validation: Incompatible types. Required: object. Actual: string."
job-3:
secrets:
DATA_FILE:
vault: production/db/some_data@ops
script:
cat $DATA_FILE
# job-4: With extra layer "some_name", "vault" with value of type string
# Schema agrees, CI linter disagrees
# Warnings:
# - "jobs:job-4:secrets:data_file config contains unknown keys: some_name
# - "jobs:job-4:secrets:data_file config missing required keys: vault"
job-4:
secrets:
DATA_FILE:
some_name:
vault: production/db/some_data@ops
script:
cat $DATA_FILE
Possible fixes
Remove the outer "additionalProperties" (which does not require key "vault") from the problematic code.
"secrets": {
"type": "object",
"additionalProperties": { # Remove!
"type": "object", # Remove!
"additionalProperties": {
"type": "object",
"properties": {
"vault": {
"oneOf": [
{
"type": "string",
},
{
"type": "object",
}
]
}
},
"required": ["vault"]
}
} # Remove!
},
The code author links to approaches to testing this and surrounding code because, of course, a fix should come with tests. Links repeated here: