diff --git a/.github/workflows/build_and_release.yml b/.github/workflows/build_and_release.yml new file mode 100644 index 0000000..29454a1 --- /dev/null +++ b/.github/workflows/build_and_release.yml @@ -0,0 +1,80 @@ +name: Full CI Build (and Release) + +on: + push: + branches: + - '**' + pull_request: + +jobs: + build-project: + runs-on: ubuntu-24.04 + env: + # Static env vars + + # Github runners limited to 2 cores, 7Gb RAM + # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources + MAX_WORKERS: 3 + # Fixed ssh-agent socket so multiple steps can use the same agent + # if needs be. Used by update_gh_pages.sh + SSH_AUTH_SOCK: "/tmp/ssh-agent-stroom.sock" + steps: + + - name: Install dependencies + id: install_dependencies + run: | + # libxml2-utils needed for xmllint + sudo apt-get update + sudo apt-get install -y libxml2-utils + + - name: Checkout code + id: checkout_code + uses: actions/checkout@v3 + with: + # Set this so it gets the annotated commit, not the commit being tagged. + # Which means we can get the release msg + # See https://github.com/actions/runner/issues/712 + ref: ${{ github.ref }} + + - name: Setup Java + id: setup_java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - name: Set Environment Variables + id: set_env_var + env: + # Needed for authenticated api calls to avoid rate limit + # Github provides this temporary token automatically + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ${GITHUB_WORKSPACE}/.github/workflows/scripts/setup_env_vars.sh + + # Separate step to show what is visible across steps + - name: Build Environment Info + id: build_info + run: | + ${ACTIONS_SCRIPTS_DIR}/dump_env_vars.sh + + - name: Run full build + id: run_build + env: + # Needed for authenticated api calls to avoid rate limit + # Github provides this temporary token automatically + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pushd "${BUILD_DIR}" > /dev/null + echo -e "${GREEN}Running ${BLUE}ci_build.sh${NC}" + ./ci_build.sh + echo -e "${GREEN}Finished running build script${NC}" + + - name: Release to GitHub + id: create_release + if: ${{ env.BUILD_IS_SCHEMA_RELEASE == 'true' }} + env: + # Github provided secret + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: "${ACTIONS_SCRIPTS_DIR}/create_github_release.sh" + diff --git a/.github/workflows/scripts/create_github_release.sh b/.github/workflows/scripts/create_github_release.sh new file mode 100755 index 0000000..251f5be --- /dev/null +++ b/.github/workflows/scripts/create_github_release.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +set -eo pipefail +IFS=$'\n\t' + +setup_echo_colours() { + # Exit the script on any error + set -e + + # shellcheck disable=SC2034 + if [ "${MONOCHROME}" = true ]; then + RED='' + GREEN='' + YELLOW='' + BLUE='' + BLUE2='' + DGREY='' + NC='' # No Colour + else + RED='\033[1;31m' + GREEN='\033[1;32m' + YELLOW='\033[1;33m' + BLUE='\033[1;34m' + BLUE2='\033[1;34m' + DGREY='\e[90m' + NC='\033[0m' # No Colour + fi +} + +debug_value() { + local name="$1"; shift + local value="$1"; shift + + if [ "${IS_DEBUG}" = true ]; then + echo -e "${DGREY}DEBUG ${name}: ${value}${NC}" + fi +} + +debug() { + local str="$1"; shift + + if [ "${IS_DEBUG}" = true ]; then + echo -e "${DGREY}DEBUG ${str}${NC}" + fi +} + +main() { + IS_DEBUG=false + #SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + + setup_echo_colours + + echo -e "${GREEN}Finding asset files for release${NC}" + local asset_files=() + for asset_file in "${BUILD_DIR}/release_artefacts/"*; do + echo -e "${GREEN}Found asset file: ${BLUE}${asset_file}${NC}" + asset_files+=("${asset_file}") + done + + local args=() + if [[ ${GITHUB_REF} =~ .*(beta|alpha).* ]]; then + echo -e "${GREEN}Release is a pre-release${NC}" + args+=("--prerelease") + fi + + git tag \ + --list "${BUILD_TAG}" \ + --format='%(subject)%0a%0a%(contents:body)' + + local message + message="$( \ + git tag \ + --list "${BUILD_TAG}" \ + --format='%(subject)%0a%0a%(contents:body)')" + + echo -e "${GREEN}Creating release for tag ${BLUE}${BUILD_TAG}${GREEN} with message:${NC}" + echo -e "${DGREY}------------------------------------------------------------------------${NC}" + echo -e "${DGREY}${message}${NC}" + echo -e "${DGREY}------------------------------------------------------------------------${NC}" + + + # Create the release on GitHub using the annotated tag that triggered + # this build + # See https://cli.github.com/manual/gh_release_create + gh release create \ + --title "${BUILD_TAG}" \ + --notes "${message}" \ + --verify-tag \ + "${args[@]}" \ + "${BUILD_TAG}" \ + "${asset_files[@]}" + + echo "${GREEN}Release created for tag ${BLUE}${BUILD_TAG}${NC}" +} + +main "$@" + +# vim: set tabstop=2 shiftwidth=2 expandtab: diff --git a/.github/workflows/scripts/dump_env_vars.sh b/.github/workflows/scripts/dump_env_vars.sh new file mode 100755 index 0000000..ca530a6 --- /dev/null +++ b/.github/workflows/scripts/dump_env_vars.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -eo pipefail + +if [[ -z "${ACTIONS_SCRIPTS_DIR}" ]]; then + echo "ACTIONS_SCRIPTS_DIR not set" + exit 1 +fi + +"${ACTIONS_SCRIPTS_DIR}/echo_variables.sh" \ + "git version" "$(git --version)" \ + "GITHUB_EVENT_NAME" "$GITHUB_EVENT_NAME" \ + "GITHUB_REF" "$GITHUB_REF" \ + "GITHUB_SHA" "$GITHUB_SHA" \ + "GITHUB_WORKSPACE" "$GITHUB_WORKSPACE" \ + "BUILD_BRANCH" "$BUILD_BRANCH" \ + "BUILD_COMMIT" "$BUILD_COMMIT" \ + "BUILD_DIR" "$BUILD_DIR" \ + "BUILD_NUMBER" "$BUILD_NUMBER" \ + "BUILD_TAG" "$BUILD_TAG" \ + "BUILD_IS_PULL_REQUEST" "$BUILD_IS_PULL_REQUEST" \ + "BUILD_IS_SCHEMA_RELEASE" "$BUILD_IS_SCHEMA_RELEASE" \ + "ACTIONS_SCRIPTS_DIR" "$ACTIONS_SCRIPTS_DIR" \ + "PWD" "$PWD" \ + "HOME" "$HOME" + diff --git a/.github/workflows/scripts/echo_variables.sh b/.github/workflows/scripts/echo_variables.sh new file mode 100755 index 0000000..13d7c87 --- /dev/null +++ b/.github/workflows/scripts/echo_variables.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +# Simple script to echo pairs of variable names and their values, +# e.g. ./echo_variables.sh HOME $HOME "Docker version" "$(docker --version)" +# results in: +# HOME: [/home/dev] +# Docker version: [Docker version 20.10.6, build 370c289] + +set -eo pipefail +IFS=$'\n\t' + +setup_echo_colours() { + # Exit the script on any error + set -e + + # shellcheck disable=SC2034 + if [ "${MONOCHROME}" = true ]; then + RED='' + GREEN='' + YELLOW='' + BLUE='' + BLUE2='' + DGREY='' + NC='' # No Colour + else + RED='\033[1;31m' + GREEN='\033[1;32m' + YELLOW='\033[1;33m' + BLUE='\033[1;34m' + BLUE2='\033[1;34m' + DGREY='\e[90m' + NC='\033[0m' # No Colour + fi +} + +debug_value() { + local name="$1"; shift + local value="$1"; shift + + if [ "${IS_DEBUG}" = true ]; then + echo -e "${DGREY}DEBUG ${name}: ${value}${NC}" + fi +} + +debug() { + local str="$1"; shift + + if [ "${IS_DEBUG}" = true ]; then + echo -e "${DGREY}DEBUG ${str}${NC}" + fi +} + +main() { + IS_DEBUG=false + + setup_echo_colours + + local max_padding_str=' ' + + while (( "$#" >= 2 )); do + local name="${1}" + local value="${2}" + shift 2 + printf \ + "${GREEN}%s${NC}: %s [${BLUE}%s${NC}]\n" \ + "${name}" \ + "${max_padding_str:${#name}}" \ + "${value}" + done +} + +main "$@" diff --git a/.github/workflows/scripts/setup_env_vars.sh b/.github/workflows/scripts/setup_env_vars.sh new file mode 100755 index 0000000..d53793e --- /dev/null +++ b/.github/workflows/scripts/setup_env_vars.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +set -eo pipefail + +# Set variables in github's special env file which are then automatically +# read into env vars in each subsequent step + +is_schema_release=false + +echo -e "${GREEN}GITHUB_REF: ${BLUE}${GITHUB_REF}${NC}" + +if [[ ${GITHUB_REF} =~ ^refs/tags/ ]]; then + # This is build is for a git tag + # strip off the 'refs/tags/' bit + tag_name="${GITHUB_REF#refs/tags/}" + if [[ "${tag_name}" =~ ^v ]]; then + # e.g. 'v4.0.2' + is_schema_release=true + echo "tag_name=${tag_name}" + fi +elif [[ ${GITHUB_REF} =~ ^refs/heads/ ]]; then + # This build is just a commit on a branch + # strip off the 'ref/heads/' bit + build_branch="${GITHUB_REF#refs/heads/}" +fi + +# Brace block means all echo stdout get appended to GITHUB_ENV +{ + # Map the GITHUB env vars to our own + echo "BUILD_DIR=${GITHUB_WORKSPACE}" + echo "BUILD_COMMIT=${GITHUB_SHA}" + + build_number="${GITHUB_RUN_NUMBER}" + echo "BUILD_NUMBER=${build_number}" + + echo "ACTIONS_SCRIPTS_DIR=${GITHUB_WORKSPACE}/.github/workflows/scripts" + + if [[ ${GITHUB_REF} =~ ^refs/heads/ ]]; then + echo "BUILD_BRANCH=${build_branch}" + fi + + # Only do a release based on our schedule, e.g. nightly + # Skip release if we have same commit as last time + if [[ "${is_schema_release}" = "true" ]]; then + echo "BUILD_IS_SCHEMA_RELEASE=true" + echo "BUILD_TAG=${GITHUB_REF#refs/tags/}" + else + echo "BUILD_IS_SCHEMA_RELEASE=false" + fi + + if [[ ${GITHUB_REF} =~ ^refs/pulls/ ]]; then + echo "BUILD_IS_PULL_REQUEST=true" + else + echo "BUILD_IS_PULL_REQUEST=false" + fi + +} >> "${GITHUB_ENV}" diff --git a/.github/workflows/scripts/update_gh_pages.sh b/.github/workflows/scripts/update_gh_pages.sh new file mode 100755 index 0000000..65c5d15 --- /dev/null +++ b/.github/workflows/scripts/update_gh_pages.sh @@ -0,0 +1,169 @@ +#!/usr/bin/env bash + +# This script will replicate all files found in gh_pages_source_dir into +# a subdirectory of the gh-pages git branch. The subdirectory name will be the +# minor version, i.e. if the version is v7.1.2 then the files will be replicated +# into ./v7.1/ +# This means we will have a subdirectory for each minor version and each new +# patch release will update the content for its minor version. +# The replication from the source uses rsync to add/update/delete in the +# destination directory as required to ensure the destination subdirectory +# matches the source. +# Following replication the changes are commited and pushed so that they are +# available on github.io. +set -eo pipefail +IFS=$'\n\t' + +setup_echo_colours() { + # Exit the script on any error + set -e + + # shellcheck disable=SC2034 + if [ "${MONOCHROME}" = true ]; then + RED='' + GREEN='' + YELLOW='' + BLUE='' + BLUE2='' + DGREY='' + NC='' # No Colour + else + RED='\033[1;31m' + GREEN='\033[1;32m' + YELLOW='\033[1;33m' + BLUE='\033[1;34m' + BLUE2='\033[1;34m' + DGREY='\e[90m' + NC='\033[0m' # No Colour + fi +} + +debug_value() { + local name="$1"; shift + local value="$1"; shift + + if [ "${IS_DEBUG}" = true ]; then + echo -e "${DGREY}DEBUG ${name}: ${value}${NC}" + fi +} + +debug() { + local str="$1"; shift + + if [ "${IS_DEBUG}" = true ]; then + echo -e "${DGREY}DEBUG ${str}${NC}" + fi +} + +setup_ssh_agent() { + # See if there is already a socket for ssh-agent + if [[ -S "${SSH_AUTH_SOCK}" ]]; then + echo -e "${GREEN}ssh-agent already bound to ${BLUE}SSH_AUTH_SOCK${NC}" + else + # Start ssh-agent and add our private ssh deploy key to it + echo -e "${GREEN}Starting ssh-agent${NC}" + ssh-agent -a "${SSH_AUTH_SOCK}" > /dev/null + fi + + # SSH_DEPLOY_KEY is the private ssh key that corresponds to the public key + # that is held in the 'deploy keys' section of the stroom repo on github + # https://github.com/gchq/stroom/settings/keys + echo -e "${GREEN}Adding ssh key${NC}" + ssh-add - <<< "${SSH_DEPLOY_KEY}" +} + +main() { + IS_DEBUG=false + + setup_echo_colours + + echo -e "${GREEN}Setting up variables${NC}" + + local repo_uri="git@github.com:${GITHUB_REPOSITORY}.git" + local remote_name="origin" + local gh_pages_branch="gh-pages" + # Dir where we clone the gh-pages branch down to + local gh_pages_clone_dir="${GITHUB_WORKSPACE}/gh-pages-clone" + # Dir where our new gh-pages content is to be found + local gh_pages_source_dir="${GITHUB_WORKSPACE}/gh-pages" + + #local minor_version + #minor_version=$(echo "${BUILD_TAG}" | grep -oP "^v[0-9]+\.[0-9]+") + #local gh_pages_versioned_dir="${gh_pages_clone_dir}/${minor_version}" + #local version_file="${gh_pages_versioned_dir}/version.txt" + + # At some point we will use versioned dirs, but not yet + local gh_pages_versioned_dir + if [[ "${BUILD_BRANCH}" = "master" ]]; then + gh_pages_versioned_dir="${gh_pages_clone_dir}" + else + gh_pages_versioned_dir="${gh_pages_clone_dir}/${BUILD_BRANCH}" + fi + + echo -e "${GREEN}Using destination gh-pages dir" \ + "${BLUE}${gh_pages_versioned_dir}${NC}" + + setup_ssh_agent + + # Clone the repo with just the gh-pages branch + echo -e "${GREEN}Cloning branch ${BLUE}${gh_pages_branch}${GREEN} to" \ + "${BLUE}${gh_pages_clone_dir}${NC}" + git clone \ + --branch "${gh_pages_branch}" \ + --single-branch \ + "${repo_uri}" \ + "${gh_pages_clone_dir}" + + pushd "${gh_pages_clone_dir}" > /dev/null + + mkdir -p "${gh_pages_versioned_dir}" + + echo -e "${GREEN}Dumping contents (maxdepth 1) of ${BLUE}${gh_pages_source_dir}${NC}" + find "${gh_pages_source_dir}/" -maxdepth 1 + + # Update the whole of gh-pages + echo -e "${GREEN}Rsyncing gh-pages content from" \ + "${BLUE}${gh_pages_source_dir}${GREEN} to" \ + "${BLUE}${gh_pages_clone_dir}${NC}" + rsync \ + --verbose \ + --human-readable \ + --archive \ + --delete \ + --exclude='.git/' \ + "${gh_pages_source_dir}/" \ + "${gh_pages_clone_dir}/" + + #echo -e "${GREEN}Writing version ${BLUE}${BUILD_TAG}${GREEN} to" \ + #"${BLUE}${version_file}${NC}" + #echo -e "${BUILD_TAG}" > "${version_file}" + + git config user.name "$GITHUB_ACTOR" + git config user.email "${GITHUB_ACTOR}@bots.github.com" + + echo -e "${GREEN}Adding all new/changed files${NC}" + git add --all + + local change_count + change_count="$(git status --porcelain | wc -l)" + if [[ "${change_count}" -gt 0 ]]; then + echo -e "${GREEN}Committing changes${NC}" + git commit \ + -a \ + -m "Updated GitHub Pages" + + #git remote set-url "$remote_name" "$repo_uri" # includes access token + echo -e "${GREEN}Pushing changes to ${BLUE}${remote_name} ${gh_pages_branch}${NC}" + git \ + push \ + --force-with-lease \ + "${remote_name}" \ + "${gh_pages_branch}" + else + echo -e "${GREEN}No changes to commit${NC}" + fi + + popd > /dev/null +} + +main "$@" diff --git a/ci_build.sh b/ci_build.sh new file mode 100755 index 0000000..aa252ce --- /dev/null +++ b/ci_build.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash + +set -eo pipefail + +setup_echo_colours() { + # Exit the script on any error + set -e + + # shellcheck disable=SC2034 + if [ "${MONOCHROME}" = true ]; then + RED='' + GREEN='' + YELLOW='' + BLUE='' + BLUE2='' + DGREY='' + NC='' # No Colour + else + RED='\033[1;31m' + GREEN='\033[1;32m' + YELLOW='\033[1;33m' + BLUE='\033[1;34m' + BLUE2='\033[1;34m' + DGREY='\e[90m' + NC='\033[0m' # No Colour + fi +} + +prepare_for_schema_release() { + echo -e "${GREEN}Preparing for a schema release${NC}" + prepare_release_artefacts +} + +validate_source_schema() { + # validate the source schema - probably overkill as java will validate + # the generated schemas + + echo -e "::group::Validating source schema" + xmllint \ + --noout \ + --schema http://www.w3.org/2001/XMLSchema.xsd \ + "${BUILD_DIR}/event-logging.xsd" + echo "::endgroup::" + + echo -e "::group::Validating versions in schema file" + ./validateSchemaVersions.py "${SCHEMA_VERSION}" + echo "::endgroup::" +} + +build_schema_variants() { + echo -e "::group::Running schema transformations" + # Run the transformations + java \ + -jar lib/event-logging-transformer-v4.1.0-all.jar \ + ./pipelines \ + ./detection.xsd + + GENERATED_DIR="./pipelines/generated" + + ls -l "${GENERATED_DIR}" + + if [[ "${BUILD_IS_SCHEMA_RELEASE}" = "true" ]]; then + echo -e "${GREEN}Copying build artefacts for release${NC}" + + echo "Deleting generated schemas that are not release artifacts" + + # Copy the schemas to the release dir for upload to gh releases + cp "${GENERATED_DIR}"/detection-v*-safe.xsd "${RELEASE_ARTEFACTS_DIR}/" + cp "${GENERATED_DIR}"/detection-v*.xsd "${RELEASE_ARTEFACTS_DIR}/" + fi + echo "::endgroup::" +} + +dump_build_info() { + echo "::group::Build info" + + #Dump all the env vars to the console for debugging + echo -e "PWD: [${GREEN}$(pwd)${NC}]" + echo -e "BUILD_DIR: [${GREEN}${BUILD_DIR}${NC}]" + echo -e "BUILD_NUMBER: [${GREEN}${BUILD_NUMBER}${NC}]" + echo -e "BUILD_COMMIT: [${GREEN}${BUILD_COMMIT}${NC}]" + echo -e "BUILD_BRANCH: [${GREEN}${BUILD_BRANCH}${NC}]" + echo -e "BUILD_TAG: [${GREEN}${BUILD_TAG}${NC}]" + echo -e "BUILD_IS_PULL_REQUEST: [${GREEN}${BUILD_IS_PULL_REQUEST}${NC}]" + echo -e "BUILD_IS_SCHEMA_RELEASE: [${GREEN}${BUILD_IS_SCHEMA_RELEASE}${NC}]" + echo -e "RELEASE_ARTEFACTS_DIR: [${GREEN}${RELEASE_ARTEFACTS_DIR}${NC}]" + echo -e "SCHEMA_VERSION: [${GREEN}${SCHEMA_VERSION}${NC}]" + + java --version + + echo "::endgroup::" +} + +create_dir() { + local dir="${1:?dir not set}"; shift + echo -e "${GREEN}Creating directory ${BLUE}${dir}${NC}" + mkdir -p "${dir}" +} + +main() { + if [ -n "$BUILD_TAG" ]; then + #Tagged commit so use that as our stroom version, e.g. v3.0.0 + SCHEMA_VERSION="${BUILD_TAG}" + else + SCHEMA_VERSION="SNAPSHOT" + fi + + local RELEASE_ARTEFACTS_DIR_NAME="release_artefacts" + local RELEASE_ARTEFACTS_DIR="${BUILD_DIR}/${RELEASE_ARTEFACTS_DIR_NAME}" + + dump_build_info + + echo "::group::Create dirs" + create_dir "${RELEASE_ARTEFACTS_DIR}" + echo "::endgroup::" + + validate_source_schema + # Run the gradle build to generate the different forms of the schema + build_schema_variants + + if [[ "${BUILD_IS_SCHEMA_RELEASE}" = "true" ]]; then + prepare_for_schema_release + else + echo -e "${GREEN}Not a release so skipping releaase preparation${NC}" + # Clear out any artefacts to be on the safe side + rm -rf "${RELEASE_ARTEFACTS_DIR:?}/*" + fi +} + +main "$@" diff --git a/detection.xsd b/detection.xsd index adfa7cb..6ef32ee 100644 --- a/detection.xsd +++ b/detection.xsd @@ -14,7 +14,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + diff --git a/validateSchemaVersions.py b/validateSchemaVersions.py new file mode 100755 index 0000000..45ab875 --- /dev/null +++ b/validateSchemaVersions.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +#********************************************************************** +# Copyright 2024 Crown Copyright +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#********************************************************************** + + +#********************************************************************** +# Script to ensure all the version numbers in the detection +# XMLSchema are valid +#********************************************************************** + + +import os +import re +import sys +import xml.etree.ElementTree as ET + +SCHEMA_FILENAME = "detection.xsd" + +root_path = os.path.dirname(os.path.realpath(__file__)) + +def getMinorVersion(versionStr): + minorVer = re.match("[0-9]*\\.([0-9]*)[.-].*", versionStr).group(1) + return minorVer + +def validateVersions(newVersion, schemaFile): + + if (newVersion): + newVersionNum = re.sub(r'^v', "", newVersion) + print("Gradle build version: %s" % newVersionNum) + + if (not schemaFile): + schemaFile = SCHEMA_FILENAME + + if (not os.path.isfile(schemaFile)): + print("ERROR - Schema file %s doesn't exist" % schemaFile) + exit(1) + + print("") + print("Validating file %s" % schemaFile) + + # pattern = re.compile("xmlns:evt\"event-logging:.*\"") + xsdFile = open(schemaFile, 'r') + filetext = xsdFile.read() + xsdFile.close() + matches = re.findall("xmlns:det=\"detection:([^\"]*)\"", filetext) + if (len(matches) != 1): + raise ValueError("Unexpected matches for evt namespace", matches) + namespaceVersion = matches[0] + print("namespace version: [%s]" % namespaceVersion) + + xml_root = ET.parse(schemaFile).getroot() + + targetNamespaceAttr = xml_root.get("targetNamespace") + targetNamespaceVersion = re.match(".*:(.*)$", targetNamespaceAttr).group(1) + print("targetNamespace: [%s]" % targetNamespaceVersion) + + versionAttrVersion = xml_root.get("version") + print("version: [%s]" % versionAttrVersion) + + idAttr = xml_root.get("id") + idAttrVersion = re.match("detection-v?(.*)$", idAttr).group(1) + print("id: [%s]" % idAttrVersion) + + print("") + versionRegex = "[0-9]+\\.[0-9]+(\\.[0-9]+|-(alpha|beta)\\.[0-9]+)" + + if (newVersion and not re.match(".*SNAPSHOT", newVersionNum)): + if (versionAttrVersion != newVersionNum): + raise ValueError("version attribute and planned version do not match", versionAttrVersion, newVersionNum) + + if (not re.match(versionRegex, versionAttrVersion)): + raise ValueError("version attribute does not match the valid regex", versionAttrVersion, versionRegex) + + # In an ideal world we would increment the namespace version when we make + # a breaking change to the schema but that has all sorts of implications + # on existing pipelines, xslts and content packs that would all need changing. + if (not versionAttrVersion.startswith(targetNamespaceVersion)): + print("Major version of the version attribute %s does not match the targetNamespace version %s" % (versionAttrVersion, targetNamespaceVersion)) + # raise ValueError("Major version of the version attribute does not match the targetNamespace version", versionAttrVersion, targetNamespaceVersion) + + minorVer = getMinorVersion(versionAttrVersion) + + # print enumVersions + + if (namespaceVersion != targetNamespaceVersion): + raise ValueError("namespace version and targetNamespace version do not match", namespaceVersion, targetNamespaceVersion) + + if (versionAttrVersion != idAttrVersion): + raise ValueError("version attribute and id attribute do not match", versionAttrVersion, idAttrVersion) + + + + +# Script starts here +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +print(sys.argv) + +if len(sys.argv) == 2: + newVersion = sys.argv[1] + schemaFile = None +elif len(sys.argv) == 3: + newVersion = sys.argv[1] + schemaFile = sys.argv[2] +else: + newVersion = None + schemaFile = None + +print("version [%s], schema file [%s]" % (newVersion, schemaFile)) + +validateVersions(newVersion, schemaFile) + +print("") +print("Done!") +exit(0)