{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://catalog.lintel.tools/schemas/schemastore/bx-ci/latest.json",
  "description": "CI configuration for Amdocs Bill Experience projects",
  "x-lintel": {
    "source": "https://www.schemastore.org/bxci.schema-3.x.json",
    "sourceSha256": "8cffee454c7366532b7f6209771a88097cb9840090211455960b5f94a9c2dfbb",
    "fileMatch": [
      "**/bxci.yaml",
      "**/bxci.yml"
    ],
    "parsers": [
      "yaml"
    ]
  },
  "type": "object",
  "properties": {
    "project": {
      "description": "Project properties",
      "type": "object",
      "properties": {
        "name": {
          "description": "Project's name (used by Jenkins, Docker and Sonar)",
          "type": "string"
        },
        "type": {
          "description": "Project type",
          "enum": [
            "npm",
            "maven",
            "mvn"
          ],
          "default": "mvn"
        },
        "settings": {
          "description": "ID of a managed maven or npm Jenkins file",
          "type": "string",
          "examples": [
            "bx-maven-settings",
            "bx-npm-settings"
          ]
        }
      },
      "additionalProperties": false
    },
    "config": {
      "type": "object",
      "properties": {
        "jenkins_runtime": {
          "type": "object",
          "properties": {
            "docker": {
              "type": "object",
              "description": "Specifies how to build the Docker container (from an existing image or from a local Dockerfile)",
              "properties": {
                "image": {
                  "description": "Prebuilt Docker image (has precedence over dockerfile)",
                  "type": "string",
                  "examples": [
                    "remote-host.com/image-name:tag"
                  ]
                },
                "dockerfile": {
                  "$ref": "#/$defs/dockerfile",
                  "description": "Path to a local Dockerfile",
                  "examples": [
                    ".ci/Dockerfile"
                  ]
                }
              },
              "additionalProperties": false
            }
          },
          "required": [
            "docker"
          ],
          "additionalProperties": false
        },
        "branch": {
          "type": "object",
          "description": "Describes on which branch names a build will be run",
          "properties": {
            "branch_pattern": {
              "$ref": "#/$defs/branchPattern"
            },
            "disable_validation": {
              "description": "Disables branch name validation",
              "type": "boolean",
              "default": false
            }
          },
          "additionalProperties": false
        },
        "build": {
          "type": "object",
          "properties": {
            "clean_workspace_after_run": {
              "type": "boolean",
              "description": "Whether Jenkins workspace should be cleaned after the build",
              "default": true
            },
            "commit_time_threshold": {
              "oneOf": [
                {
                  "type": "integer",
                  "const": 0
                },
                {
                  "type": "string",
                  "pattern": "^\\d+[mhd]$"
                }
              ],
              "description": "Commit age threshold. Disables automated builds older than this parameter. When 0, this feature is disabled",
              "default": false,
              "examples": [
                0,
                "2m",
                "30m",
                "1d",
                "30m",
                "10d"
              ]
            },
            "checkmarx": {
              "$ref": "#/$defs/checkmarx",
              "description": "Adds a Static Analysis stage for CheckMarx. See <https://www.jenkins.io/doc/pipeline/steps/checkmarx/> for all the configuration options."
            },
            "static_analysis": {
              "$ref": "#/$defs/sonar",
              "description": "Adds a Static Analysis stage for Sonar."
            }
          },
          "additionalProperties": false
        },
        "cache": {
          "type": "object",
          "description": "Cache configuration for projects built inside Docker containers",
          "properties": {
            "repository": {
              "$ref": "#/$defs/binaryRepository"
            },
            "items": {
              "type": "array",
              "description": "List of cache types",
              "items": {
                "$ref": "#/$defs/cacheItem"
              }
            }
          },
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    },
    "services": {
      "type": "array",
      "description": "Additional services required by the project or application.",
      "items": {
        "enum": [
          "Postgres",
          "Postgis",
          "Redis",
          "Mssql",
          "Mysql",
          "Mongodb",
          "Elasticsearch"
        ]
      },
      "uniqueItems": true
    },
    "environment": {
      "type": "object",
      "description": "Custom environment variables to be added to the pipeline",
      "propertyNames": {
        "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
      }
    },
    "jenkinsEnvironment": {
      "type": "array",
      "description": "Jenkins environment variables that are passed to the Docker container",
      "uniqueItems": true,
      "items": {
        "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
        "type": "string"
      }
    },
    "stages": {
      "type": "object",
      "title": "Stages",
      "description": "Defines the stages and steps required to build the project.",
      "patternProperties": {
        "^\\w+( \\w+)*$": {
          "$ref": "#/$defs/stage",
          "description": "Stage name in the Jenkins pipeline"
        }
      }
    },
    "output": {
      "type": "object",
      "description": "Describes artifacts generated after all the stages have been run",
      "properties": {
        "package": {
          "$ref": "#/$defs/outputPackage",
          "description": "Configuration for publishing NPM or Maven packages"
        },
        "docker": {
          "$ref": "#/$defs/outputDocker",
          "description": "Configuration for generating a Docker image"
        },
        "helm": {
          "$ref": "#/$defs/outputHelm",
          "description": "Configuration for generating a Helm chart"
        }
      },
      "additionalProperties": false
    },
    "archive": {
      "type": "array",
      "description": "List of artifacts to archive (wildcards allowed). Check out <https://www.jenkins.io/doc/pipeline/steps/core/#archiveartifacts-archive-the-artifacts>",
      "examples": [
        "target/*.jar",
        "**/*.jar",
        "target/out.txt"
      ]
    },
    "timeout": {
      "$ref": "#/$defs/timeout",
      "description": "Build timeout in seconds",
      "default": 600
    }
  },
  "required": [
    "project"
  ],
  "$defs": {
    "branchPattern": {
      "description": "Regular expression for validating branch names",
      "type": "string"
    },
    "timeout": {
      "description": "Timeout in seconds",
      "type": "integer"
    },
    "credentials": {
      "description": "Jenkins credentials ID",
      "type": "string"
    },
    "binaryRepository": {
      "type": "object",
      "description": "Binary repository details",
      "properties": {
        "address": {
          "type": "string",
          "format": "uri",
          "description": "Repository URL"
        },
        "credentials": {
          "$ref": "#/$defs/credentials",
          "description": "Jenkins credentials ID for connecting to this repository"
        }
      },
      "required": [
        "address",
        "credentials"
      ],
      "additionalProperties": false
    },
    "checkmarx": {
      "type": "object",
      "title": "CheckMarx",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": false,
          "description": "Sets whether the scan should be run"
        },
        "branch_pattern": {
          "$ref": "#/$defs/branchPattern",
          "description": "Specifies in which branches this stage will be executed",
          "default": "^master$|^release/.*$"
        },
        "groupId": {
          "type": "string",
          "default": "55",
          "description": "Fully qualified team name for the project"
        },
        "preset": {
          "type": "string",
          "default": "36",
          "description": "Scan preset for the project"
        },
        "sourceEncoding": {
          "type": "string",
          "default": "5",
          "description": "Language encoding ID associated to the source code character encoding (5: Multi-Language Scan)"
        },
        "serverUrl": {
          "type": "string",
          "default": "http://cxpbgmgmtserver/",
          "description": "Checkmarx Server URL or IP address"
        },
        "credentialsId": {
          "type": "string",
          "default": "BB-Checkmarx",
          "description": "Jenkins credentials ID"
        },
        "isProxy": {
          "type": "boolean",
          "default": false
        },
        "useOwnServerCredentials": {
          "type": "boolean",
          "default": true,
          "description": "Enables the use of the default server credentials or disables and provides server and credentials that override the defaults"
        },
        "projectName": {
          "type": "string",
          "description": "Unique project name. Will be inferred from the repository name if not provided"
        },
        "exclusionsSetting": {
          "enum": [
            "job",
            "global"
          ],
          "default": "job",
          "description": "Specifies which exclusions settings to use: global (Jenkins global settings) or job (current pipeline)"
        },
        "excludeFolders": {
          "type": "string",
          "description": "Comma separated list of folders to be excluded from the CxSAST scan",
          "examples": [
            "folder-1, folder-2, folder-3"
          ]
        },
        "filterPattern": {
          "type": "string",
          "description": "Defines the include/exclude wildcard patterns. Does not have effect when \"exclusionsSetting\" is set to \"global\"",
          "examples": [
            "\"!**/_cvs/**/*, !**/.svn/**/*, !**/.hg/**/*, !**/.git/**/*\""
          ]
        },
        "hideDebugLogs": {
          "type": "boolean",
          "default": true,
          "description": "Sets whether debug logs are visible in the job output"
        },
        "waitForResultsEnabled": {
          "type": "boolean",
          "default": true,
          "description": "Sets whether the scan should be executed synchronously (default). The Synchronous mode allows viewing scan results in Jenkins"
        },
        "vulnerabilityThresholdEnabled": {
          "type": "boolean",
          "default": true,
          "description": "Sets whether the scan should fail if the number of vulnerabilities is above the configured thresholds. This option is only available if the waitForResultsEnabled parameter is enabled"
        },
        "highThreshold": {
          "type": "integer",
          "default": 0,
          "description": "Sets the maximum number of High vulnerabilities allowed"
        },
        "mediumThreshold": {
          "type": "integer",
          "default": 10,
          "description": "Sets the maximum number of Medium vulnerabilities allowed"
        },
        "lowThreshold": {
          "type": "integer",
          "default": null,
          "description": "Sets the maximum number of Low vulnerabilities allowed"
        }
      },
      "additionalProperties": false
    },
    "sonar": {
      "type": "object",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": true
        },
        "breaks_build": {
          "type": "boolean",
          "description": "Waits for analysis result and breaks the build when the project fails for some quality gates",
          "default": false
        },
        "branch_analysis": {
          "type": "boolean",
          "description": "Indicates whether sonnar server supports branch analysis, to provide dedicated parameters.",
          "default": true
        },
        "branch_pattern": {
          "type": "string",
          "description": "Indicates on which branches static analysis will be performed.",
          "examples": [
            "^master$|^release/.+$",
            "master"
          ]
        },
        "image": {
          "type": "string",
          "description": "Prebuilt Docker image for running scan into it. If not specified, it will use the same image used for main build.",
          "examples": [
            "myrepo:port/my-awesome-image:1.2.3"
          ]
        },
        "timeout": {
          "$ref": "#/$defs/timeout",
          "description": "Seconds to wait for the result of the quality gate. Only applies when breaks_build is set to true",
          "default": 120
        },
        "exclusions": {
          "type": "string",
          "description": "Comma separated list of wildcard patterns defining files to be excluded from the SonarQube scan",
          "examples": [
            "**/excluded-folder/**, **/example/*.html"
          ]
        }
      },
      "additionalProperties": false
    },
    "when": {
      "type": "object",
      "title": "When",
      "description": "Condition that should be met to run this step",
      "properties": {
        "branch": {
          "$ref": "#/$defs/branchPattern",
          "title": "Branch"
        }
      }
    },
    "steps": {
      "type": "array",
      "description": "List of steps to run",
      "title": "Steps"
    },
    "singleStage": {
      "type": "object",
      "title": "Stage",
      "properties": {
        "steps": {
          "$ref": "#/$defs/steps"
        },
        "when": {
          "$ref": "#/$defs/when"
        }
      },
      "required": [
        "steps"
      ],
      "additionalProperties": false
    },
    "failFast": {
      "type": "boolean",
      "title": "Fail Fast",
      "default": false,
      "description": "Forces parallel stages to all be aborted when one of them fails"
    },
    "parallelStage": {
      "type": "object",
      "title": "Parallel Stage",
      "properties": {
        "when": {
          "$ref": "#/$defs/when"
        },
        "fail_fast": {
          "$ref": "#/$defs/failFast"
        },
        "parallel": {
          "type": "object",
          "description": "List of stages to be executed in parallel",
          "patternProperties": {
            "^\\w+( \\w+)*$": {
              "$ref": "#/$defs/singleStage",
              "description": "Stage name in the Jenkins pipeline"
            }
          }
        }
      },
      "required": [
        "parallel"
      ],
      "additionalProperties": false
    },
    "stage": {
      "type": "object",
      "properties": {
        "when": {
          "$ref": "#/$defs/when"
        },
        "steps": {
          "$ref": "#/$defs/steps"
        },
        "fail_fast": {
          "$ref": "#/$defs/failFast"
        },
        "parallel": {
          "type": "object",
          "title": "Parallel",
          "patternProperties": {
            "^\\w+( \\w+)*$": {
              "$ref": "#/$defs/singleStage"
            }
          }
        }
      },
      "anyOf": [
        {
          "$ref": "#/$defs/singleStage"
        },
        {
          "$ref": "#/$defs/parallelStage"
        }
      ],
      "additionalProperties": false
    },
    "releaseChannel": {
      "type": "string",
      "description": "Release channel name"
    },
    "releaseChannelBranch": {
      "$ref": "#/$defs/branchPattern",
      "description": "Indicates on which branches the artifact will be published"
    },
    "dockerfile": {
      "description": "Dockerfile path",
      "type": "string"
    },
    "context": {
      "description": "Dockerfile context. If not set defaults to dockerfile file path (parent folder)",
      "type": "string"
    },
    "outputDockerImage": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "Docker image name"
        },
        "dockerfile": {
          "$ref": "#/$defs/dockerfile",
          "description": "Path to Dockerfile used to generate the docker image"
        },
        "context": {
          "$ref": "#/$defs/context",
          "description": "Path to the desired docker build context."
        },
        "args": {
          "type": "array",
          "description": "List of build args (--build-arg) to pass in docker build",
          "title": "Docker build args",
          "items": {
            "$ref": "#/$defs/outputDockerBuildArgs"
          }
        },
        "vulnerability_scan": {
          "type": "object",
          "description": "Configuration for running vulnerability scans on published Docker images",
          "title": "Vulnerability scan",
          "properties": {
            "enabled": {
              "type": "boolean",
              "default": true,
              "description": "Whether the vulnerability scan step should be run"
            }
          }
        }
      },
      "required": [
        "name"
      ],
      "anyOf": [
        {
          "properties": {
            "dockerfile": {
              "$ref": "#/$defs/dockerfile",
              "description": "Path to Dockerfile used to generate the docker image"
            }
          },
          "required": [
            "dockerfile"
          ],
          "type": "object"
        },
        {
          "properties": {
            "context": {
              "$ref": "#/$defs/context",
              "description": "Path to the desired docker build context."
            }
          },
          "required": [
            "context"
          ],
          "type": "object"
        }
      ],
      "additionalProperties": false
    },
    "outputDocker": {
      "type": "object",
      "properties": {
        "images": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/outputDockerImage"
          }
        },
        "publish": {
          "$ref": "#/$defs/outputDockerPublish",
          "description": "Docker publishing information. If not present, no images will be published"
        },
        "multiArch": {
          "type": "object",
          "properties": {
            "enabled": {
              "type": "boolean",
              "default": false,
              "description": "Whether the multi-arch build should be enabled"
            },
            "architectures": {
              "type": "array",
              "items": {
                "type": "string",
                "description": "List of architectures to build",
                "examples": [
                  "amd64",
                  "arm64",
                  "arm"
                ]
              }
            }
          }
        }
      },
      "required": [
        "images"
      ],
      "additionalProperties": false
    },
    "outputDockerPublish": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/dockerReleaseChannel"
      }
    },
    "outputDockerBuildArgs": {
      "type": "object",
      "oneOf": [
        {
          "properties": {
            "key": {
              "type": "string",
              "description": "ARG name"
            },
            "value": {
              "type": "string",
              "description": "Value of the ARG"
            },
            "additionalProperties": false
          },
          "required": [
            "key",
            "value"
          ],
          "type": "object"
        },
        {
          "properties": {
            "key": {
              "type": "string",
              "description": "ARG name"
            },
            "env": {
              "type": "string",
              "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
              "description": "Environment variable whose value will be used to set the ARG"
            },
            "additionalProperties": false
          },
          "required": [
            "key",
            "env"
          ],
          "type": "object"
        }
      ],
      "properties": {
        "key": {
          "type": "string",
          "description": "ARG name"
        },
        "env": {
          "type": "string",
          "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
          "description": "Environment variable whose value will be used to set the ARG"
        },
        "value": {
          "type": "string",
          "description": "Value of the ARG"
        }
      }
    },
    "dockerReleaseChannel": {
      "type": "object",
      "properties": {
        "channel": {
          "$ref": "#/$defs/releaseChannel"
        },
        "branch": {
          "$ref": "#/$defs/releaseChannelBranch"
        },
        "registry": {
          "type": "string",
          "description": "Docker registry. Must include protocol (http|https) and port",
          "format": "uri"
        },
        "credentials": {
          "$ref": "#/$defs/credentials",
          "description": "Jenkins credentials ID for publishing into the specified Docker registry"
        }
      },
      "required": [
        "channel",
        "branch",
        "registry",
        "credentials"
      ],
      "additionalProperties": false
    },
    "outputHelmChart": {
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "description": "Path to the Helm chart directory"
        },
        "updates": {
          "type": "array",
          "description": "List of files to update",
          "items": {
            "$ref": "#/$defs/outputHelmUpdates"
          }
        }
      },
      "required": [
        "path"
      ],
      "additionalProperties": false
    },
    "outputHelm": {
      "type": "object",
      "properties": {
        "charts": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/outputHelmChart"
          }
        },
        "publish": {
          "$ref": "#/$defs/outputHelmPublish",
          "description": "Helm chart publishing configuration. If not present, no charts will be published"
        }
      },
      "required": [
        "publish"
      ],
      "additionalProperties": false
    },
    "outputHelmUpdates": {
      "type": "object",
      "required": [
        "file",
        "properties"
      ],
      "properties": {
        "file": {
          "type": "string",
          "description": "Name (including path from Helm object path) of the file to be updated. Only supports yaml files"
        },
        "properties": {
          "type": "array",
          "description": "A list of properties to update. It can be updated with a fixed value or environment variable",
          "items": {
            "$ref": "#/$defs/outputHelmUpdatesProperties"
          }
        }
      },
      "additionalProperties": false
    },
    "outputHelmUpdatesProperties": {
      "type": "object",
      "oneOf": [
        {
          "properties": {
            "key": {
              "type": "string",
              "description": "Yaml property (full path) to be updated"
            },
            "env": {
              "type": "string",
              "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
              "description": "Environment variable whose value will be used to update the property"
            },
            "additionalProperties": false
          },
          "required": [
            "key",
            "env"
          ],
          "additionalProperties": false,
          "type": "object"
        },
        {
          "properties": {
            "key": {
              "type": "string",
              "description": "Yaml property (full path) to be updated"
            },
            "value": {
              "type": "string",
              "description": "Value to update the given property"
            }
          },
          "required": [
            "key",
            "value"
          ],
          "additionalProperties": false,
          "type": "object"
        }
      ]
    },
    "outputHelmPublish": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/helmReleaseChannel"
      }
    },
    "helmReleaseChannel": {
      "type": "object",
      "properties": {
        "channel": {
          "$ref": "#/$defs/releaseChannel"
        },
        "branch": {
          "$ref": "#/$defs/releaseChannelBranch"
        },
        "repository": {
          "type": "string",
          "format": "uri",
          "description": "Helm chart repository. Must include protocol, host, port (if needed) and path"
        },
        "credentials": {
          "$ref": "#/$defs/credentials",
          "description": "Jenkins credentials Id for this repository for uploading the chart"
        }
      },
      "required": [
        "channel",
        "branch",
        "repository",
        "credentials"
      ],
      "additionalProperties": false
    },
    "outputPackage": {
      "type": "object",
      "properties": {
        "publish": {
          "$ref": "#/$defs/outputPackagePublish",
          "description": "Package publish configuration."
        }
      },
      "required": [
        "publish"
      ],
      "additionalProperties": false
    },
    "outputPackagePublish": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/packagePublishChannel"
      }
    },
    "packagePublishChannel": {
      "type": "object",
      "properties": {
        "channel": {
          "$ref": "#/$defs/releaseChannel"
        },
        "branch": {
          "$ref": "#/$defs/releaseChannelBranch"
        },
        "registry": {
          "type": "string",
          "description": "NPM registry (env variable or registry URL)",
          "examples": [
            "NPM_PUBLISH_REGISTRY",
            "NPM_SNAPSHOT_REGISTRY",
            "https://registry.npmjs.org"
          ]
        },
        "credentials": {
          "$ref": "#/$defs/credentials",
          "description": "Jenkins credentials ID for publishing into the specified Docker registry"
        },
        "maven_releases_repo": {
          "type": "string",
          "description": "Maven repository for deploying releases"
        },
        "maven_snapshots_repo": {
          "type": "string",
          "description": "Maven repository for deploying snapshots"
        },
        "params": {
          "type": "string",
          "description": "Optional params for npm publish or mvn deploy command.",
          "examples": [
            "--tag latest",
            "-Dmaven.test.skip=true"
          ]
        }
      },
      "required": [
        "channel",
        "branch"
      ],
      "additionalProperties": false
    },
    "cacheItem": {
      "type": "object",
      "properties": {
        "type": {
          "enum": [
            "maven",
            "npm",
            "local"
          ],
          "description": "Cache type",
          "default": "maven"
        },
        "enabled": {
          "type": "boolean",
          "description": "Sets whether this cache type is enabled",
          "default": false
        },
        "source": {
          "type": "string",
          "description": "Location of the cache in the Jenkins workspace",
          "default": ".ci-cache/<type>"
        },
        "target": {
          "type": "string",
          "description": "Location of the cache directory inside the Docker container",
          "default": "/container-path/directory"
        }
      },
      "required": [
        "type",
        "enabled"
      ],
      "additionalProperties": false
    }
  }
}
