Configuration schema reference
We publish a JSON schema for cg-workshop.yml (and the multi-file variant
cg-workshop/*.yml) to:
- Ensure configuration and documentation match
- Make editing easier for teams managing Workshop configuration of their projects and subgroups
- Make editing easier for operators of Workshop
- Support linting configuration early in CI/CD pipelines, instead of waiting to find out at the end when configuration is deployed
Use the JSONSchemaViewer below to explore the schema.
Click the ▶︎ arrows to unfold sections.
Loading ....
Source
The current schema is always available here and is shown below.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://workshop.cloud.gov/workshop/workshop-schemas/-/raw/main/cg-workshop.schema.json",
"title": "Workshop Configuration",
"description": "Schema for the Cloud.gov Workshop configuration files. Top level keys `subgroups` and `projects` are valid for Customer configs. Top level keys `namespaces` and `users` are valid for the Workshop-controlled configurations.",
"type": "object",
"additionalProperties": false,
"properties": {
"namespaces": {
"description": "Workshop top level groups. This key is invalid in customer config files.",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^([\\w\\-\\.]+)$": {
"$ref": "#/$defs/namespace"
}
}
},
"projects": {
"description": "Workshop customer projects.",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^([\\w\\-\\.]+)$": {
"$ref": "#/$defs/project"
}
}
},
"subgroups": {
"description": "Workshop customer sub-groups.",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^([\\w\\-\\.]+)$": {
"$ref": "#/$defs/subgroup"
}
}
},
"teams": {
"description": "Team groups to provision. These groups are used specifically for role management.",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^([\\w\\-\\.]+)$": {
"$ref": "#/$defs/team"
}
}
},
"users": {
"description": "Workshop users to provision. This key is invalid in customer config files.",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^([a-z0-9_\\-\\.\\+]+@[a-z0-9\\-.]+\\.[a-z0-9\\-]{2,63})$": {
"$ref": "#/$defs/user"
}
}
}
},
"$defs": {
"namespace": {
"description": "Namespace (top level group) - The key can use any sequence of letters, numbers, underscores, hypens, and dots",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"description": "Friendly name for the group",
"type": "string"
},
"description": {
"description": "Friendly description for the group",
"type": "string"
},
"path": {
"description": "Path (slug) for group - Defaults to the group key name",
"type": "string",
"pattern": "^([\\w\\-\\.]+)$"
},
"config_project": {
"description": "Optional overrides for the related customer configuration project",
"type": "object",
"additionalProperties": false,
"properties": {
"approvals_required": {
"description": "Number of approvals needed for a MR to the config project",
"type": "number",
"minimum": 0
},
"merge_method": {
"description": "Default merge method",
"type": "string",
"enum": [
"merge",
"rebase_merge",
"ff"
]
},
"require_owner_approval": {
"description": "Require at least one approval from a namespace owner before merging",
"type": "boolean"
},
"squash_option": {
"description": "Squash commits on merge request merge",
"type": "string",
"enum": [
"always",
"default_off",
"default_on",
"never"
]
}
}
},
"custom_attributes": {
"description": "[Optional] Key/value pairs to set as custom attributes (Requires admin permission)",
"type": "object",
"patternProperties": {
"^([\\w\\-]+)$": {
"description": "Value for the given custom_attribute",
"type": "string"
}
}
},
"dr_group": {
"description": "Group is required to bootstrap Workshop",
"type": "boolean"
},
"visibility": {
"description": "Namespace visibility - private (members only), public (including anonymous), or internal (visible to other Workshop users)",
"type": "string",
"enum": [
"internal",
"private",
"public"
]
},
"use_custom_template": {
"description": "Use a custom project template",
"type": "boolean"
},
"owners": {
"description": "List of owners for the group",
"type": "array",
"items": {
"type": "string",
"pattern": "^([a-z0-9_\\-\\.\\+]+@[a-z0-9\\-.]+\\.gov)$"
},
"minItems": 1,
"uniqueItems": true
},
"wiki_access_level": {
"description": "Whether the namespace group wiki is enabled, disabled, or private",
"type": "string",
"enum": [
"disabled",
"enabled",
"private"
]
},
"runner": {
"description": "Runner pool configuration",
"type": "object",
"additionalProperties": false,
"properties": {
"allow_ssh": {
"description": "Allow SSH access to manager and egress spaces. Defaults to false",
"type": "boolean"
},
"cg_emails": {
"description": "List of Cloug.gov operators allowed to interact with the group runner spaces",
"type": "array",
"items": {
"type": "string",
"pattern": "^([a-z0-9_\\-\\.\\+]+@gsa\\.gov)$"
},
"minItems": 1,
"uniqueItems": true
},
"concurrency": {
"description": "Maximum concurrent jobs to run per-worker manager",
"type": "integer",
"exclusiveMinimum": 0,
"exclusiveMaximum": 100
},
"docker_hub_user": {
"description": "Docker Hub username for runner workers to pull images",
"type": "string"
},
"docker_hub_token_env_var": {
"description": "Name of the environment variable holding the token for the Docker Hub user",
"type": "string"
},
"egress_https_mode": {
"description": "Egress HTTPS proxy mode for runner workers and services",
"type": "string",
"enum": [
"http",
"https",
"both"
]
},
"grant_workers_developer_role": {
"description": "Allow runner workers to SSH to runner services",
"type": "boolean"
},
"instances": {
"description": "Number of worker managers to run",
"type": "integer",
"exclusiveMinimum": 0,
"exclusiveMaximum": 2
},
"pool_size": {
"description": "Size of the runner worker pool",
"type": "string",
"enum": [
"small",
"medium",
"large",
"extra_large"
]
},
"register": {
"description": "Register the runner pool to the group",
"type": "boolean"
},
"service_egress_ports": {
"description": "List of TCP ports the egress proxy will allow outbound connection to for job services",
"type": "array",
"items": {
"type": "number",
"exclusiveMinimum": 1,
"exclusiveMaxiumum": 65536
},
"minItems": 1,
"uniqueItems": true
},
"service_egress_allowlist": {
"description": "List of additional fully qualified domain names to allow outbound to the Internet by runner job services over HTTPS",
"type": "array",
"items": {
"type": "string",
"pattern": "^([\\w\\-\\.\\*]+)$"
},
"minItems": 1,
"uniqueItems": true
},
"service_egress_denylist": {
"description": "List of fully qualified domain names to block outbound to the Internet by runner job services over HTTPS",
"type": "array",
"items": {
"type": "string",
"pattern": "^([\\w\\-\\.\\*]+)$"
},
"minItems": 1,
"uniqueItems": true
},
"technologies": {
"description": "List of technologies used under the group requiring egress allowance over HTTPS byrunner workers",
"type": "array",
"items": {
"type": "string",
"pattern": "^([a-z0-9_\\-]+)$"
},
"minItems": 1,
"uniqueItems": true
},
"worker_allowlist": {
"description": "List of additional fully qualified domain names to allow outbound to the Internet by runner workers over HTTPS",
"type": "array",
"items": {
"type": "string",
"pattern": "^([\\w\\-\\.\\*]+)$"
},
"minItems": 1,
"uniqueItems": true
},
"worker_denylist": {
"description": "List of fully qualified domain names to block outbound to the Internet by runner workers over HTTPS",
"type": "array",
"items": {
"type": "string",
"pattern": "^([\\w\\-\\.\\*]+)$"
},
"minItems": 1,
"uniqueItems": true
},
"worker_egress_ports": {
"description": "List of TCP ports the egress proxy will allow outbound connection to for runner workers",
"type": "array",
"items": {
"type": "number",
"exclusiveMinimum": 1,
"exclusiveMaxiumum": 65536
},
"minItems": 1,
"uniqueItems": true
},
"unsafe_egress": {
"description": "Allow unfettered outbound Internet access [DANGER!]",
"type": "boolean"
}
}
}
}
},
"project": {
"description": "Project - The key can use any sequence of letters, numbers, underscores, hypens, and dots",
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"description": "Friendly name for the project",
"type": "string"
},
"description": {
"description": "Friendly description for the project",
"type": "string"
},
"visibility": {
"description": "Project visibility - private (members only), public (including anonymous), or internal (visible to other Workshop users)",
"type": "string",
"enum": [
"internal",
"private",
"public"
]
},
"subgroup_key": {
"description": "Subgroup project is under - Defaults to the namespace",
"type": "string",
"pattern": "^([\\w\\-\\.\\/]+)$"
},
"archived": {
"description": "Archive - When true sets repository to read-only state",
"type": "boolean"
},
"approvals_required": {
"description": "Number of approvals needed for a MR",
"type": "number",
"minimum": 0
},
"allow_mr_committers_to_approve_merge_requests": {
"description": "Allow merge request committers to approve their own merge requests. Defaults to false. A merge request committer is a user who has added commits to the merge request's source branch.",
"type": "boolean"
},
"auto_cancel_pending_pipelines": {
"description": "",
"type": "boolean"
},
"auto_devops_enabled": {
"description": "",
"type": "boolean"
},
"ci_pipeline_variables_minimum_override_role": {
"description": "",
"type": "string",
"enum": [
"developer",
"maintainer",
"owner"
]
},
"ci_separated_caches": {
"description": "",
"type": "boolean"
},
"compliance_frameworks": {
"description": "List of compliance framework names to apply to the project. Names must exist in the namespace already. See https://workshop.cloud.gov/help/user/compliance/compliance_center/compliance_frameworks_report/#create-a-new-compliance-framework for more details.",
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"container_expiration_policy": {
"description": "",
"type": "object",
"properties": {
"cadence": {
"description": "",
"type": "string"
},
"enabled": {
"description": "",
"type": "boolean"
},
"older_than": {
"description": "",
"type": "string"
}
}
},
"container_registry_access_level": {
"description": "",
"type": "string",
"enum": [
"disabled",
"enabled"
]
},
"default_branch": {
"description": "",
"type": "string",
"pattern": "^([\\w\\-\\.\\/]+)$"
},
"import_id": {
"description": "Existing project ID to import as a new IaC managed resource",
"type": "number"
},
"initialize_with_readme": {
"description": "",
"type": "boolean"
},
"lfs_enabled": {
"description": "",
"type": "boolean"
},
"merge_access_level": {
"description": "Specify the role that can merge Merge Requests to the default branch. Defaults to 'developer'",
"type": "string",
"enum": [
"no one",
"developer",
"maintainer"
]
},
"push_access_level": {
"description": "Specify the role that can push directly to the default branch. Defaults to 'no one'",
"type": "string",
"enum": [
"no one",
"developer",
"maintainer"
]
},
"skip_branch_protection": {
"description": "Whether to skip branch protection rules on the default branch. Defaults to false, which applies Workshop's branch protection rules.",
"type": "boolean"
},
"model_registry_access_level": {
"description": "",
"type": "string",
"enum": [
"disabled",
"enabled"
]
},
"namespace": {
"description": "[DEPRECATING] Namespace path project is under - Defaults to the namespace / subgroup_key",
"type": "string",
"pattern": "^([\\w\\-\\.\\/]+)$"
},
"allow_merge_on_skipped_pipeline": {
"description": "Whether to treat skipped pipelines as successful when merging. Defaults to false",
"type": "boolean"
},
"only_allow_merge_if_all_discussions_are_resolved": {
"description": "Whether merge requests can be merged only after all discussions are resolved. Defaults to true",
"type": "boolean"
},
"only_allow_merge_if_pipeline_succeeds": {
"description": "Whether merge requests can be merged only if the pipeline succeeds. Defaults to true",
"type": "boolean"
},
"path": {
"description": "Project path (slug name) - Overrides the default path derived from the key name",
"type": "string",
"pattern": "^([\\w\\-\\.]+)$"
},
"packages_enabled": {
"description": "",
"type": "boolean"
},
"protected_tags": {
"description": "Project tags that are protected",
"type": "array",
"items": {
"description": "List of protected tags for the project",
"type": "object",
"additionalProperties": false,
"required": [
"tag"
],
"properties": {
"tag": {
"description": "Wildcard pattern or tag name",
"type": "string"
},
"create_access_level": {
"description": "Access levels allowed to create. Default is set to maintainer",
"type": "string",
"enum": [
"no one",
"developer",
"maintainer"
]
}
}
}
},
"public_jobs": {
"description": "",
"type": "boolean"
},
"remove_source_branch_after_merge": {
"description": "",
"type": "boolean"
},
"resolve_outdated_diff_discussions": {
"description": "",
"type": "boolean"
},
"group_roles": {
"description": "Additional groups outside of the inheritence structure to share the project with, giving the group's members access to the project - Supports default roles docs.gitlab.com/user/permissions/#default-roles with a key of lower cased plural role name (e.g. The key developers will share the project with the group and give members the developer role)",
"type": "object",
"patternProperties": {
"^\\w+s$": {
"description": "List of group paths to assign as role project members, e.g. 'subgroup/roles/developers'",
"type": "array",
"items": {
"type": "string",
"pattern": "^([\\w\\-\\.\\/]+)$"
}
}
},
"additionalProperties": false
},
"mr_review_groups": {
"description": "Configure required reviews for Merge Requests. Each key gives the name to the approval group, and the list of roles or teams defines who may grant an approval for this approval group.",
"type": "object",
"patternProperties": {
"^.*$": {
"type": "array",
"items": {
"description": "A list of groups that must approve Merge Requests against this project's default and protected branches, e.g. 'teams/platform-developers'",
"type": "string",
"pattern": "^([\\w\\-\\.\\/]+)$"
}
}
}
},
"shared_runners_enabled": {
"description": "",
"type": "boolean"
},
"snippets_enabled": {
"description": "Whether project code snippets are enabled. Deprecated in favor of `snippets_access_level`",
"deprecated": true,
"type": "boolean"
},
"snippets_access_level": {
"description": "Whether project code snippets are enabled, disabled, or private.",
"type": "string",
"enum": [
"disabled",
"enabled",
"private"
]
},
"wiki_access_level": {
"description": "Whether the project wiki is enabled, disabled, or private",
"type": "string",
"enum": [
"disabled",
"enabled",
"private"
]
},
"avatar": {
"description": "",
"type": "string"
},
"avatar_hash": {
"description": "",
"type": "string"
},
"forked_from_project_id": {
"description": "",
"type": "number"
},
"import_url": {
"description": "https url to import repository from. Use with `mirror: true` to set up a pull mirror to keep the repository up to date.",
"type": "string"
},
"import_url_password_env_var": {
"description": "Name of the environment variable holding the `import_url_password` value. Used with `import_url_username`.",
"type": "string"
},
"import_url_username": {
"description": "Username that can access `import_url`. Required for private repositories. Optional for public repositories.",
"type": "string"
},
"mirror": {
"description": "",
"type": "boolean"
},
"push_rules": {
"description": "Rules for pushing to the repository",
"type": "object",
"additionalProperties": false,
"properties": {
"commit_committer_check": {
"description": "Users can only push commits to this repository that were committed with one of their own verified emails.",
"type": "boolean"
},
"member_check": {
"description": "Restrict commits by author (email) to existing GitLab users.",
"type": "boolean"
},
"deny_delete_tag": {
"description": "Do not allow deleting tags with a push",
"type": "boolean"
},
"max_file_size": {
"description": "",
"type": "number"
},
"prevent_secrets": {
"description": "Reject any files that are likely to contain secrets",
"type": "boolean"
},
"reject_unsigned_commits": {
"description": "",
"type": "boolean"
},
"reject_non_dco_commits": {
"description": "Reject commits that do not have a valid DCO sign-off",
"type": "boolean"
},
"author_email_regex": {
"description": "",
"type": "string"
},
"branch_name_regex": {
"description": "",
"type": "string"
},
"commit_message_negative_regex": {
"description": "",
"type": "string"
},
"commit_message_regex": {
"description": "",
"type": "string"
},
"file_name_regex": {
"description": "",
"type": "string"
}
}
},
"security_policy_project_scope": {
"description": "When given, this project will be set up as a Security Policy project. 'namespace' will register it on the entire namespace. 'assigned' will make it available for assignment via security_policy_project_key.",
"type": "string",
"enum": [
"namespace",
"assigned"
]
},
"security_policy_project": {
"description": "If given, the project at the key will provide security policies to this project.",
"type": "object",
"properties": {
"key": {
"description": "The key of the security policy project in the `projects:` section of the config file. The security policy project must also have `security_policy_project_scope` set to 'assigned' to be assignable to other projects.",
"type": "string",
"pattern": "^([\\w\\-\\.]+)$"
},
"import": {
"description": "Whether to import the connection of this project with thesecurity policy project given by key. Defaults to false.",
"type": "boolean"
}
},
"required": [
"key"
]
}
}
},
"subgroup": {
"description": "Subgroup (any group other than a top level namespace) - The key can use any sequence of letters, numbers, underscores, hypens, and dots",
"type": "object",
"required": [
"name",
"visibility"
],
"additionalProperties": false,
"properties": {
"name": {
"description": "Friendly name for the group",
"type": "string"
},
"path": {
"description": "Path (slug) for group - Defaults to the group key name",
"type": "string",
"pattern": "^([\\w\\-\\.]+)$"
},
"parent_path": {
"description": "Parent group full path for the subgroup. Defaults to the top level namespace",
"type": "string",
"pattern": "^([\\w\\-\\.\\/]+)$"
},
"description": {
"description": "Friendly description of the group",
"type": "string"
},
"import_id": {
"description": "Existing subgroup ID to import as a new IaC managed resource",
"type": "number"
},
"members": {
"description": "Roles and their memberships under the subgroup - Supports both default roles docs.gitlab.com/user/permissions/#default-roles and custom roles https://docs.gitlab.com/user/custom_roles/ with a key of lower cased plural role name (e.g. The key developers will create a group Developers that give members the developer role)",
"type": "object",
"patternProperties": {
"^[\\w\\-\\.\\/]+$": {
"description": "List of users to assign as role group members",
"type": "array"
}
}
},
"group_roles": {
"description": "Additional groups outside of the inheritance structure to grant a role on the subgroup. This gives the group's members access to the subgroup and all of its projects. Supports default roles <https://docs.gitlab.com/user/permissions/#default-roles> by matching the key to lowercased and pluralized role names (e.g. The key 'developers' will share the project with the group and give members the `developer` role)",
"type": "object",
"patternProperties": {
"^\\w+s$": {
"description": "List of group paths to assign as role project members, e.g. 'teams/platform-developers'",
"type": "array",
"items": {
"type": "string",
"pattern": "^([\\w\\-\\.\\/]+)$"
}
}
},
"additionalProperties": false
},
"visibility": {
"description": "Subgroup visibility - private (members only), public (including anonymous), or internal (visible to other Workshop users)",
"type": "string",
"enum": [
"internal",
"private",
"public"
]
},
"wiki_access_level": {
"description": "Whether the group wiki is enabled, disabled, or private",
"type": "string",
"enum": [
"disabled",
"enabled",
"private"
]
},
"security_policy_project": {
"description": "If given, the project at the key will provide security policies to this project.",
"type": "object",
"properties": {
"key": {
"description": "The key of the security policy project in the `projects:` section of the config file. The security policy project must also have `security_policy_project_scope` set to 'assigned' to be assignable to other projects.",
"type": "string",
"pattern": "^([\\w\\-\\.]+)$"
},
"import": {
"description": "Whether to import the connection of this project with thesecurity policy project given by key. Defaults to false.",
"type": "boolean"
}
},
"required": [
"key"
]
}
}
},
"team": {
"description": "Team group - used to create groups for easy @mentions and group-based assignments — not necessarily for role-based access control. The key can use any sequence of letters, numbers, underscores, hyphens, and dots.",
"type": "object",
"required": [
"name",
"members"
],
"additionalProperties": false,
"properties": {
"name": {
"description": "Friendly name for the team",
"type": "string"
},
"description": {
"description": "Friendly description of the team",
"type": "string"
},
"namespace_role": {
"description": "Role to assign the team on the full namespace. Defaults to none (no access)",
"type": "string"
},
"managed_projects_role": {
"description": "Role to assign the team for Workshop's configuration projects — i.e., the configuration project this schema applies to, the templates project, and other Workshop-generated config projects. Defaults to `developer`, set to `none` to remove access",
"type": "string"
},
"members": {
"description": "List of users to assign as team members.",
"type": "array",
"items": {
"description": "Each item is a Workshop username",
"type": "string",
"pattern": "^([a-z0-9_\\-\\.\\+]+)$"
},
"minItems": 1,
"uniqueItems": true
}
}
},
"user": {
"description": "User object - The key must be the user's email address",
"type": "object",
"additionalProperties": false,
"required": [
"name"
],
"properties": {
"custom_attributes": {
"description": "[Optional] Key/value pairs to set as custom attributes (Requires admin permission)",
"type": "object",
"patternProperties": {
"^([\\w\\-]+)$": {
"description": "Value for the given custom_attribute",
"type": "string"
}
}
},
"import_id": {
"description": "[Optional] Existing GitLab user ID on the system to import",
"type": "integer"
},
"name": {
"description": "Full name of user",
"type": "string",
"pattern": "^([\\w'\\- ]+)$"
},
"note": {
"description": "[Optional] Additional notes about the user",
"type": "string"
},
"projects_limit": {
"description": "[Optional] Personal project limit",
"type": "integer"
},
"state": {
"description": "[Optional] Forced state of the user account",
"type": "string",
"enum": [
"active",
"blocked",
"deactivated"
]
},
"username": {
"description": "[Optional] Custom username - Overrides the default username from the user email address",
"type": "string",
"pattern": "^([a-zA-Z0-9][\\w\\-\\.]{1,254})$"
}
}
}
}
}