From f1a56a184d8d1b26b4438bf176dadcdf6174e3d3 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Fri, 7 Oct 2022 03:10:24 +0200 Subject: [PATCH 01/18] CI/CD for SA5 Signed-off-by: Miguel Angel Reina Ortega --- sa5/.gitlab-ci.yml | 93 +++++++++++++++++++++++++++++++++++++ sa5/generate_changemarks.sh | 24 ++++++++++ sa5/lint-data-models.sh | 81 ++++++++++++++++++++++++++++++++ sa5/validate-all.sh | 85 +++++++++++++++++++++++++++++++++ sa5/validate-data-models.sh | 41 ++++++++++++++++ 5 files changed, 324 insertions(+) create mode 100644 sa5/.gitlab-ci.yml create mode 100755 sa5/generate_changemarks.sh create mode 100755 sa5/lint-data-models.sh create mode 100755 sa5/validate-all.sh create mode 100755 sa5/validate-data-models.sh diff --git a/sa5/.gitlab-ci.yml b/sa5/.gitlab-ci.yml new file mode 100644 index 0000000..93e60e1 --- /dev/null +++ b/sa5/.gitlab-ci.yml @@ -0,0 +1,93 @@ +# CI/CD: +# +# RESOLVE triggered by: +# - any (branch commit) +# VALIDATION triggered by: +# - any (branch commit) +# +# GENERATION triggered by: +# - merge request +# + +variables: + LOGFILE_YANG: "yang-validation.log" + LOGFILE_LINT: "yang-linting.log" + LOGFILE_OPENAPI: "openapi-validation.log" + +stages: + - resolve + - validation + - generation + +Resolve: + stage: resolve + only: + - pushes + - merge_requests + script: + - echo 'Resolve' + - git clone https://forge.3gpp.org/rep/reinaortega/3gpp-scripts.git scripts/ + after_script: + - ls + artifacts: + paths: + - scripts/ + expire_in: 5 mins #It should be deleted after last stage of this pipeline + +YANG Strict: + stage: validation + only: + - pushes + needs: + - job: Resolve + artifacts: true + script: + - echo 'YANG Strict' + - ./scripts/sa5/validate-data-models.sh . + after_script: + - ls + artifacts: + paths: + - ${LOGFILE_YANG} + +YANG 3GPP Checks: + stage: validation + only: + - pushes + needs: + - job: Resolve + artifacts: true + script: + - echo 'YANG 3GPP Checks' + - ./scripts/sa5/lint-data-models.sh . + artifacts: + paths: + - ${LOGFILE_LINT} + +Validate OpenAPI: + stage: validation + only: + - pushes + needs: + - job: Resolve + artifacts: true + script: + - echo 'Validate OpenAPI' + - ./scripts/sa5/validate-all.sh ./OpenAPI + artifacts: + paths: + - ./OpenAPI/${LOGFILE_OPENAPI} + +CR contribution: + stage: generation + when: on_success + only: + - merge_requests + dependencies: + - Resolve + script: + - echo 'CR contribution' + - ./scripts/sa5/generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} + artifacts: + paths: + - ./*.docx \ No newline at end of file diff --git a/sa5/generate_changemarks.sh b/sa5/generate_changemarks.sh new file mode 100755 index 0000000..d47abc3 --- /dev/null +++ b/sa5/generate_changemarks.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +DOCKER_IMAGE=forge.3gpp.org:5050/tools/3gpp-scripts/forgelib:v1.0.0 + +echo "\n------ Checking for docker image --------" +docker pull "$DOCKER_IMAGE" + +echo "------ Removing previous outputs --------" +rm *.docx + +echo "------ Parsing repo URL --------" + +HOST_URL=$(echo $1 | cut -d'/' -f 1-3) +PROJECT_NAME=$(echo $1 | cut -d'/' -f 5- | cut -d'.' -f 1) +echo "HOST URL:" $HOST_URL +echo "PROJECT NAME:" $PROJECT_NAME +echo "PROJECT ID:" $2 +echo "MERGE IID:" $3 + +echo "\n------ Generating change marks --------" +docker container run --rm -v$(pwd):/tmp/ "$DOCKER_IMAGE" forgelib-changedocs -vv --outPath=/tmp/ "$HOST_URL" "$2" "$PROJECT_NAME" "$3" + +exit 0 + diff --git a/sa5/lint-data-models.sh b/sa5/lint-data-models.sh new file mode 100755 index 0000000..b9d8b4f --- /dev/null +++ b/sa5/lint-data-models.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# Copyright ETSI 2020 + +LOGFILE=yang-linting.log +DOCKER_IMG=etsiforge/pyang:2.4.0-3gpp-d410f57 + +echo "------ Switching to $1 folder --------" +cd $1 + +echo "------ Content of the folder ------" +ls + +echo "------ Checking for previous logs ------" +if [ -f "$LOGFILE" ] ; then + echo "Found previous log. Removing it" + rm "$LOGFILE" +fi + +echo "------ Linting modified YANG files ------" +# If there are no YANG, JSON or XML files, then simply exit +ls | grep -q 'yang' +found_data_models=$? +if [ ! $found_data_models ] ; then + echo "-- No YANG files." + exit 0 +fi + +echo "------ pyYANG Version ------" +docker run --rm -v $(pwd)/yang-models:/yang "${DOCKER_IMG}" pyang --version + +echo "------ Linting modified YANG files ------" +# Display all errors and warnings to the user. Errors are allowed. +docker pull -q "${DOCKER_IMG}" +# Linting only yang files that have changed in last commit +files_changed=`git log --raw -n 1 |grep "^:.*yang-models/.*yang"| cut -d '/' -f 2` +echo $files_changed +external_files_changed=`git log --raw -n 1 |grep "^:.*yang-models/external-yams/.*yang"| cut -d '/' -f 2` +echo $external_files_modified +if [ -d "changed-yang-models" ]; then + echo "Removing changed-yang-models dir" + rm -rf "changed-yang-models" +fi +mkdir changed-yang-models +mkdir changed-yang-models/external-yams +if [ ! -z "$files_changed" ] ; then + cd yang-models + cp $files_changed ../changed-yang-models/ + cd .. +fi + +if [ ! -z "$external_files_changed" ] ; then + cd yang-models/external-yams + cp $external_files_changed ../changed-yang-models/external-yams + cd ../.. +fi + +if [ ! -z "$files_changed" ] || [ ! -z "$external_files_changed" ] ; then + docker run --rm -v $(pwd):/yang "${DOCKER_IMG}" "/bin/sh" -c 'pyang --3gpp -p yang-models -p yang-models/external-yams changed-yang-models/*.yang' 2>>$LOGFILE >>$LOGFILE + ret=$? +else + echo "-- No YANG files modified." + exit 0 +fi + +#Validate all yang files +#docker run --rm -v $(pwd)/yang-models:/yang "${DOCKER_IMG}" "/bin/sh" -c 'pyang --3gpp -p external-yams _3gpp-*.yang' 2>>$LOGFILE >>$LOGFILE +#ret=$? + +echo "Output of Linting commad saved to $LOGFILE." + +echo "------ Linting result ------" +echo $ret + +if [ $ret == 1 ] ; then + echo "Some issues were collected by the linter, but they are treated as warnings and are not failing the validation." + echo "To see the full output of the linter, download the archived artifact named '$LOGFILE'." +fi + +# exit $ret +exit 0 + diff --git a/sa5/validate-all.sh b/sa5/validate-all.sh new file mode 100755 index 0000000..4c35f43 --- /dev/null +++ b/sa5/validate-all.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Copyright ETSI 2019-2021 +# See: https://forge.etsi.org/etsi-forge-copyright-statement.txt + +LOGFILE=openapi-validation.log +DOCKER_IMAGE=etsiforge/swagger-cli:4.0.3 + +echo -e "\n------ Switching to $1 folder --------" +cd $1 + +echo "------ Checking for previous logs ------" +if [ -f "$LOGFILE" ] ; then + echo "Found previous log. Removing it" + rm "$LOGFILE" +fi + +if [ -x "$(command -v docker)" ] ; then + RUN_IN_DOCKER=0 + echo "Using dockerized validator ($DOCKER_IMAGE)" + docker pull "$DOCKER_IMAGE" + #docker pull -q "$DOCKER_IMAGE" --> Pull quietly only from Ubuntu 20.04 +else + RUN_IN_DOCKER=1 + if [ ! -x "$(command -v swagger-cli)" ] ; then + echo "Validator swagger-cli not found. Quitting." + exit 1 + else + echo "Using local validator ($(which swagger-cli))" + fi +fi + +function validate { + echo -e "---- Validating $i: " + if [ $RUN_IN_DOCKER == 0 ] ; then + bname=$(basename "$1") + docker run --rm -v $(dirname $(realpath $1)):"/specs" $DOCKER_IMAGE swagger-cli validate "/specs/$bname" + else + swagger-cli validate "$1" + fi +} + +echo -e "\n------ Validating all YAML files (may takes several minutes) ------" +# If there are no YAML file, simply exit +ls | grep -q yaml +found_yaml=$? +if [ ! $found_yaml ] ; then + echo "-- No YAML files." + exit 0 +fi + +fres=0 +LOG="" +ERR="" +for i in ./*.yaml ; do + + MSG=$(validate "$i" 2>&1) + res=$? + if [ ! $res == 0 ] ; then + ERR="$ERR$MSG\n" + fi + LOG="$LOG$MSG\n" + fres=$(($fres||$res)) +done + +echo -e "\n-- Final validator returns $fres." | tee -a $LOGFILE +if [ $fres == 0 ] ; then + echo "No errors found, all files validate the OpenAPI definition. Below the complete log." | tee -a $LOGFILE +else + echo "Some errors found, see below the details." | tee -a $LOGFILE +fi + +if [ ! "$ERR" == "" ] ; then + echo -e "\n---- Errors detected ----" | tee -a $LOGFILE + echo -e $ERR | tee -a $LOGFILE +fi + +echo -e "\n---- Complete log of validation ----" | tee -a $LOGFILE +echo -e $LOG | tee -a $LOGFILE + +echo -e "\n------ Content of the folder ------" | tee -a $LOGFILE +ls | tee -a $LOGFILE + +# Exit code needed for jenkins to know the verdict of the build + +exit $fres diff --git a/sa5/validate-data-models.sh b/sa5/validate-data-models.sh new file mode 100755 index 0000000..eca92e3 --- /dev/null +++ b/sa5/validate-data-models.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Copyright ETSI 2020 + +LOGFILE=yang-validation.log +DOCKER_IMG=etsiforge/pyang:2.4.0-3gpp-d410f57 + +echo "------ Switching to $1 folder --------" +cd $1 + +echo "------ Content of the folder ------" +ls + +echo "------ Checking for previous logs ------" +if [ -f "$LOGFILE" ] ; then + echo "Found previous log. Removing it" + rm "$LOGFILE" +fi + +echo "------ Validating modified YANG files ------" +# If there are no YANG, JSON or XML files, then simply exit +ls | grep -q 'yang' +found_data_models=$? +if [ ! $found_data_models ] ; then + echo "-- No YANG files." + exit 0 +fi + +# This must run error-free and must display all warnings to the user +docker pull -q "${DOCKER_IMG}" +#Validate all yang files +docker run --rm -v $(pwd)/yang-models:/yang "${DOCKER_IMG}" "/bin/sh" -c 'pyang --strict -p external-yams *.yang' 2>>$LOGFILE >>$LOGFILE +ret=$? + +cat $LOGFILE + +if [ $ret == 0 ] ; then + echo "No errors found by pyang --strict validation." +fi + +exit $ret + -- GitLab From 7cf76deae16b7059612109cbb4691f384048e360 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Tue, 11 Oct 2022 11:38:55 +0200 Subject: [PATCH 02/18] Switch from branch pipeline to merge request pipeline if merge request exists Signed-off-by: Miguel Angel Reina Ortega --- sa5/.gitlab-ci.yml | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/sa5/.gitlab-ci.yml b/sa5/.gitlab-ci.yml index 93e60e1..4af8038 100644 --- a/sa5/.gitlab-ci.yml +++ b/sa5/.gitlab-ci.yml @@ -9,6 +9,13 @@ # - merge request # +workflow: + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS + when: never + - if: $CI_COMMIT_BRANCH + variables: LOGFILE_YANG: "yang-validation.log" LOGFILE_LINT: "yang-linting.log" @@ -21,9 +28,9 @@ stages: Resolve: stage: resolve - only: - - pushes - - merge_requests + # only: + # - pushes + # - merge_requests script: - echo 'Resolve' - git clone https://forge.3gpp.org/rep/reinaortega/3gpp-scripts.git scripts/ @@ -36,8 +43,8 @@ Resolve: YANG Strict: stage: validation - only: - - pushes + # only: + # - pushes needs: - job: Resolve artifacts: true @@ -52,8 +59,8 @@ YANG Strict: YANG 3GPP Checks: stage: validation - only: - - pushes + # only: + # - pushes needs: - job: Resolve artifacts: true @@ -66,8 +73,8 @@ YANG 3GPP Checks: Validate OpenAPI: stage: validation - only: - - pushes + # only: + # - pushes needs: - job: Resolve artifacts: true -- GitLab From 34cfe2beedf27ed92a45228996011172dd473fb9 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Tue, 11 Oct 2022 16:05:53 +0200 Subject: [PATCH 03/18] Removal of artifact from Resolve Signed-off-by: Miguel Angel Reina Ortega --- sa5/.gitlab-ci.yml | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/sa5/.gitlab-ci.yml b/sa5/.gitlab-ci.yml index 4af8038..d0b2ad2 100644 --- a/sa5/.gitlab-ci.yml +++ b/sa5/.gitlab-ci.yml @@ -20,6 +20,7 @@ variables: LOGFILE_YANG: "yang-validation.log" LOGFILE_LINT: "yang-linting.log" LOGFILE_OPENAPI: "openapi-validation.log" + RESOLVE_ID: "" stages: - resolve @@ -36,10 +37,15 @@ Resolve: - git clone https://forge.3gpp.org/rep/reinaortega/3gpp-scripts.git scripts/ after_script: - ls + - echo "RESOLVE_ID=${CI_JOB_ID}" >> resolveId.env + - RESOLVE_ID=${CI_JOB_ID} + - echo ${RESOLVE_ID} #>> resolveId.env artifacts: paths: - scripts/ - expire_in: 5 mins #It should be deleted after last stage of this pipeline + #expire_in: 5 min #It should be deleted after last stage of this pipeline + reports: + dotenv: resolveId.env YANG Strict: stage: validation @@ -48,6 +54,9 @@ YANG Strict: needs: - job: Resolve artifacts: true + before_script: + - | + curl "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/repository/files/sa5/validate-data-models.sh/raw?ref=master" >> validate-data-models-directly.sh script: - echo 'YANG Strict' - ./scripts/sa5/validate-data-models.sh . @@ -90,11 +99,21 @@ CR contribution: when: on_success only: - merge_requests - dependencies: - - Resolve + needs: + - job: Resolve + artifacts: true script: - echo 'CR contribution' - - ./scripts/sa5/generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} + - ./scripts/sa5/generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} artifacts: paths: - - ./*.docx \ No newline at end of file + - ./*.docx + after_script: + - echo 'Removing Resolve artifact ...' + - echo ${SA5_ACCESS_TOKEN} + - echo ${CI_API_V4_URL} + - echo ${CI_PROJECT_ID} + - echo ${RESOLVE_ID} + - | + curl --request DELETE --header "PRIVATE-TOKEN : ${SA5_ACCESS_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${RESOLVE_ID}/artifacts" + \ No newline at end of file -- GitLab From cebf23e15e133da911b13474bc569c0a6daedd5a Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Tue, 11 Oct 2022 19:39:49 +0200 Subject: [PATCH 04/18] Fetching the necessary script for each stage Signed-off-by: Miguel Angel Reina Ortega --- sa5/.gitlab-ci.yml | 103 +++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 46 deletions(-) diff --git a/sa5/.gitlab-ci.yml b/sa5/.gitlab-ci.yml index d0b2ad2..4744422 100644 --- a/sa5/.gitlab-ci.yml +++ b/sa5/.gitlab-ci.yml @@ -20,46 +20,45 @@ variables: LOGFILE_YANG: "yang-validation.log" LOGFILE_LINT: "yang-linting.log" LOGFILE_OPENAPI: "openapi-validation.log" - RESOLVE_ID: "" stages: - - resolve - validation - generation -Resolve: - stage: resolve - # only: - # - pushes - # - merge_requests - script: - - echo 'Resolve' - - git clone https://forge.3gpp.org/rep/reinaortega/3gpp-scripts.git scripts/ - after_script: - - ls - - echo "RESOLVE_ID=${CI_JOB_ID}" >> resolveId.env - - RESOLVE_ID=${CI_JOB_ID} - - echo ${RESOLVE_ID} #>> resolveId.env - artifacts: - paths: - - scripts/ - #expire_in: 5 min #It should be deleted after last stage of this pipeline - reports: - dotenv: resolveId.env +# Resolve: + # stage: resolve + # # only: + # # - pushes + # # - merge_requests + # script: + # - echo 'Resolve' + # - git clone https://forge.3gpp.org/rep/reinaortega/3gpp-scripts.git scripts/ + # after_script: + # - ls + # - echo "RESOLVE_ID=${CI_JOB_ID}" >> resolveId.env + # - RESOLVE_ID=${CI_JOB_ID} + # - echo ${RESOLVE_ID} #>> resolveId.env + # artifacts: + # paths: + # - scripts/ + # #expire_in: 5 min #It should be deleted after last stage of this pipeline + # reports: + # dotenv: resolveId.env YANG Strict: stage: validation # only: # - pushes - needs: - - job: Resolve - artifacts: true + # needs: + # - job: Resolve + # artifacts: true before_script: - | - curl "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/repository/files/sa5/validate-data-models.sh/raw?ref=master" >> validate-data-models-directly.sh + curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Fvalidate-data-models%2Esh/raw?ref=master" >> validate-data-models.sh + - chmod +x validate-data-models.sh script: - echo 'YANG Strict' - - ./scripts/sa5/validate-data-models.sh . + - ./validate-data-models.sh . after_script: - ls artifacts: @@ -70,12 +69,16 @@ YANG 3GPP Checks: stage: validation # only: # - pushes - needs: - - job: Resolve - artifacts: true + # needs: + # - job: Resolve + # artifacts: true + before_script: + - | + curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Flint-data-models%2Esh/raw?ref=master" >> lint-data-models.sh + - chmod +x lint-data-models.sh script: - echo 'YANG 3GPP Checks' - - ./scripts/sa5/lint-data-models.sh . + - ./lint-data-models.sh . artifacts: paths: - ${LOGFILE_LINT} @@ -84,12 +87,16 @@ Validate OpenAPI: stage: validation # only: # - pushes - needs: - - job: Resolve - artifacts: true + # needs: + # - job: Resolve + # artifacts: true + before_script: + - | + curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Fvalidate-all%2Esh/raw?ref=master" >> validate-all.sh + - chmod +x validate-all.sh script: - echo 'Validate OpenAPI' - - ./scripts/sa5/validate-all.sh ./OpenAPI + - ./validate-all.sh ./OpenAPI artifacts: paths: - ./OpenAPI/${LOGFILE_OPENAPI} @@ -99,21 +106,25 @@ CR contribution: when: on_success only: - merge_requests - needs: - - job: Resolve - artifacts: true + # needs: + # - job: Resolve + # artifacts: true + before_script: + - | + curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Fgenerate_changemarks%2Esh/raw?ref=master" >> generate_changemarks.sh + - chmod +x generate_changemarks.sh script: - echo 'CR contribution' - - ./scripts/sa5/generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} + - ./generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} artifacts: paths: - ./*.docx - after_script: - - echo 'Removing Resolve artifact ...' - - echo ${SA5_ACCESS_TOKEN} - - echo ${CI_API_V4_URL} - - echo ${CI_PROJECT_ID} - - echo ${RESOLVE_ID} - - | - curl --request DELETE --header "PRIVATE-TOKEN : ${SA5_ACCESS_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${RESOLVE_ID}/artifacts" + # after_script: + # - echo 'Removing Resolve artifact ...' + # - echo ${SA5_ACCESS_TOKEN} + # - echo ${CI_API_V4_URL} + # - echo ${CI_PROJECT_ID} + # - echo ${RESOLVE_ID} + # - | + # curl --request DELETE --header "PRIVATE-TOKEN : ${SA5_ACCESS_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${RESOLVE_ID}/artifacts" \ No newline at end of file -- GitLab From 2dae9c58e172d2f2245e631c6852442a19df68f5 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Wed, 12 Oct 2022 11:43:28 +0200 Subject: [PATCH 05/18] Cleanup of gitlab-ci + exposing docs generated Signed-off-by: Miguel Angel Reina Ortega --- sa5/.gitlab-ci.yml | 58 ++++++------------------------------- sa5/generate_changemarks.sh | 4 +-- 2 files changed, 11 insertions(+), 51 deletions(-) diff --git a/sa5/.gitlab-ci.yml b/sa5/.gitlab-ci.yml index 4744422..330684c 100644 --- a/sa5/.gitlab-ci.yml +++ b/sa5/.gitlab-ci.yml @@ -24,34 +24,9 @@ variables: stages: - validation - generation - -# Resolve: - # stage: resolve - # # only: - # # - pushes - # # - merge_requests - # script: - # - echo 'Resolve' - # - git clone https://forge.3gpp.org/rep/reinaortega/3gpp-scripts.git scripts/ - # after_script: - # - ls - # - echo "RESOLVE_ID=${CI_JOB_ID}" >> resolveId.env - # - RESOLVE_ID=${CI_JOB_ID} - # - echo ${RESOLVE_ID} #>> resolveId.env - # artifacts: - # paths: - # - scripts/ - # #expire_in: 5 min #It should be deleted after last stage of this pipeline - # reports: - # dotenv: resolveId.env YANG Strict: stage: validation - # only: - # - pushes - # needs: - # - job: Resolve - # artifacts: true before_script: - | curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Fvalidate-data-models%2Esh/raw?ref=master" >> validate-data-models.sh @@ -62,16 +37,12 @@ YANG Strict: after_script: - ls artifacts: + name: "$CI_JOB_NAME" paths: - ${LOGFILE_YANG} YANG 3GPP Checks: stage: validation - # only: - # - pushes - # needs: - # - job: Resolve - # artifacts: true before_script: - | curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Flint-data-models%2Esh/raw?ref=master" >> lint-data-models.sh @@ -80,16 +51,12 @@ YANG 3GPP Checks: - echo 'YANG 3GPP Checks' - ./lint-data-models.sh . artifacts: + name: "$CI_JOB_NAME" paths: - ${LOGFILE_LINT} Validate OpenAPI: stage: validation - # only: - # - pushes - # needs: - # - job: Resolve - # artifacts: true before_script: - | curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Fvalidate-all%2Esh/raw?ref=master" >> validate-all.sh @@ -98,6 +65,7 @@ Validate OpenAPI: - echo 'Validate OpenAPI' - ./validate-all.sh ./OpenAPI artifacts: + name: "$CI_JOB_NAME" paths: - ./OpenAPI/${LOGFILE_OPENAPI} @@ -106,25 +74,17 @@ CR contribution: when: on_success only: - merge_requests - # needs: - # - job: Resolve - # artifacts: true before_script: - | curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Fgenerate_changemarks%2Esh/raw?ref=master" >> generate_changemarks.sh - chmod +x generate_changemarks.sh script: - echo 'CR contribution' - - ./generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} + - mkdir docs + - ./generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} + - mkdir docs + - cp *.docx docs/ artifacts: paths: - - ./*.docx - # after_script: - # - echo 'Removing Resolve artifact ...' - # - echo ${SA5_ACCESS_TOKEN} - # - echo ${CI_API_V4_URL} - # - echo ${CI_PROJECT_ID} - # - echo ${RESOLVE_ID} - # - | - # curl --request DELETE --header "PRIVATE-TOKEN : ${SA5_ACCESS_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${RESOLVE_ID}/artifacts" - \ No newline at end of file + - docs/ + expose_as: 'Word document contribution' \ No newline at end of file diff --git a/sa5/generate_changemarks.sh b/sa5/generate_changemarks.sh index d47abc3..94eb407 100755 --- a/sa5/generate_changemarks.sh +++ b/sa5/generate_changemarks.sh @@ -6,7 +6,7 @@ echo "\n------ Checking for docker image --------" docker pull "$DOCKER_IMAGE" echo "------ Removing previous outputs --------" -rm *.docx +rm **/*.docx echo "------ Parsing repo URL --------" @@ -18,7 +18,7 @@ echo "PROJECT ID:" $2 echo "MERGE IID:" $3 echo "\n------ Generating change marks --------" -docker container run --rm -v$(pwd):/tmp/ "$DOCKER_IMAGE" forgelib-changedocs -vv --outPath=/tmp/ "$HOST_URL" "$2" "$PROJECT_NAME" "$3" +docker container run --rm -v $(pwd)/docs:/tmp/ "$DOCKER_IMAGE" forgelib-changedocs -vv --outPath=/tmp/ "$HOST_URL" "$2" "$PROJECT_NAME" "$3" exit 0 -- GitLab From 7ab2fa310df2f6e7c7e1ea0f9430880217494154 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Wed, 12 Oct 2022 17:12:45 +0200 Subject: [PATCH 06/18] Add delimiters documents for SA5 + use combine feature for CR generation Signed-off-by: Miguel Angel Reina Ortega --- sa5/.gitlab-ci.yml | 8 +++++--- sa5/generate_changemarks.sh | 4 ++-- sa5/sa5_delimiter_end.docx | Bin 0 -> 23896 bytes sa5/sa5_delimiter_start.docx | Bin 0 -> 23912 bytes 4 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 sa5/sa5_delimiter_end.docx create mode 100644 sa5/sa5_delimiter_start.docx diff --git a/sa5/.gitlab-ci.yml b/sa5/.gitlab-ci.yml index 330684c..3978428 100644 --- a/sa5/.gitlab-ci.yml +++ b/sa5/.gitlab-ci.yml @@ -78,12 +78,14 @@ CR contribution: - | curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Fgenerate_changemarks%2Esh/raw?ref=master" >> generate_changemarks.sh - chmod +x generate_changemarks.sh + - | + curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Fsa5_delimiter_start%2Edocx/raw?ref=master" >> sa5_delimiter_start.docx + - | + curl "${CI_API_V4_URL}/projects/57/repository/files/sa5%2Fsa5_delimiter_end%2Edocx/raw?ref=master" >> sa5_delimiter_end.docx script: - echo 'CR contribution' - mkdir docs - - ./generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} - - mkdir docs - - cp *.docx docs/ + - ./generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} sa5_delimiter_start.docx sa5_delimiter_end.docx artifacts: paths: - docs/ diff --git a/sa5/generate_changemarks.sh b/sa5/generate_changemarks.sh index 94eb407..1658fad 100755 --- a/sa5/generate_changemarks.sh +++ b/sa5/generate_changemarks.sh @@ -1,6 +1,6 @@ #!/bin/bash -DOCKER_IMAGE=forge.3gpp.org:5050/tools/3gpp-scripts/forgelib:v1.0.0 +DOCKER_IMAGE=forge.3gpp.org:5050/tools/3gpp-scripts/forgelib:v2.0.0 echo "\n------ Checking for docker image --------" docker pull "$DOCKER_IMAGE" @@ -18,7 +18,7 @@ echo "PROJECT ID:" $2 echo "MERGE IID:" $3 echo "\n------ Generating change marks --------" -docker container run --rm -v $(pwd)/docs:/tmp/ "$DOCKER_IMAGE" forgelib-changedocs -vv --outPath=/tmp/ "$HOST_URL" "$2" "$PROJECT_NAME" "$3" +docker container run --rm -v $(pwd):/tmp/ "$DOCKER_IMAGE" forgelib-changedocs -vv --combine --outPath=/tmp/docs --startdelimiter "/tmp/$4" --enddelimiter "/tmp/$5" "$HOST_URL" "$2" "$PROJECT_NAME" "$3" exit 0 diff --git a/sa5/sa5_delimiter_end.docx b/sa5/sa5_delimiter_end.docx new file mode 100644 index 0000000000000000000000000000000000000000..7794450d118e31c05f1f0ac655d22dfa4dea2785 GIT binary patch literal 23896 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 literal 0 HcmV?d00001 diff --git a/sa5/sa5_delimiter_start.docx b/sa5/sa5_delimiter_start.docx new file mode 100644 index 0000000000000000000000000000000000000000..6ea73fd6d4677776a4af0734ae518bc9d85ddc5c GIT binary patch literal 23912 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 W>4}vMq(g#1g29B1fk7@D!~*~iUAVgd literal 0 HcmV?d00001 -- GitLab From 04f07d2e69dc4e21cd8c51a0912b206aeec619f5 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Fri, 14 Oct 2022 17:20:15 +0200 Subject: [PATCH 07/18] CI/CD for All/5G_APIs project Signed-off-by: Miguel Angel Reina Ortega --- all/.gitlab-ci.yml | 59 +++++++++++++++++++++++++ all/generate_changemarks.sh | 25 +++++++++++ all/validate-all.sh | 85 +++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 all/.gitlab-ci.yml create mode 100644 all/generate_changemarks.sh create mode 100644 all/validate-all.sh diff --git a/all/.gitlab-ci.yml b/all/.gitlab-ci.yml new file mode 100644 index 0000000..f3c7b6c --- /dev/null +++ b/all/.gitlab-ci.yml @@ -0,0 +1,59 @@ +# CI/CD: +# +# VALIDATION triggered by: +# - any (branch commit) +# +# GENERATION triggered by: +# - merge request +# + +workflow: + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS + when: never + - if: $CI_COMMIT_BRANCH + +variables: + LOGFILE_OPENAPI: "openapi-validation.log" + +stages: + - validation + - generation + +Validate OpenAPI: + stage: validation + before_script: + - | + curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fvalidate-all%2Esh/raw?ref=master" >> validate-all.sh + - chmod +x validate-all.sh + script: + - echo 'Validate OpenAPI' + - ./validate-all.sh $(pwd) + artifacts: + name: "$CI_JOB_NAME" + paths: + - ${LOGFILE_OPENAPI} + +CR contribution: + stage: generation + when: on_success + only: + - merge_requests + before_script: + - | + curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fgenerate_changemarks%2Esh/raw?ref=master" >> generate_changemarks.sh + - chmod +x generate_changemarks.sh + # - | + # curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fall_delimiter_start%2Edocx/raw?ref=master" >> all_delimiter_start.docx + # - | + # curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fall_delimiter_end%2Edocx/raw?ref=master" >> all_delimiter_end.docx + script: + - echo 'CR contribution' + - mkdir docs + - ./generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} + #- ./generate_changemarks.sh ${CI_PROJECT_URL} ${CI_MERGE_REQUEST_PROJECT_ID} ${CI_MERGE_REQUEST_IID} all_delimiter_start.docx all_delimiter_end.docx + artifacts: + paths: + - docs/ + expose_as: 'Word document contribution' \ No newline at end of file diff --git a/all/generate_changemarks.sh b/all/generate_changemarks.sh new file mode 100644 index 0000000..86c44ba --- /dev/null +++ b/all/generate_changemarks.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +DOCKER_IMAGE=forge.3gpp.org:5050/tools/3gpp-scripts/forgelib:v2.0.0 + +echo "\n------ Checking for docker image --------" +docker pull "$DOCKER_IMAGE" + +echo "------ Removing previous outputs --------" +rm **/*.docx + +echo "------ Parsing repo URL --------" + +HOST_URL=$(echo $1 | cut -d'/' -f 1-3) +PROJECT_NAME=$(echo $1 | cut -d'/' -f 5- | cut -d'.' -f 1) +echo "HOST URL:" $HOST_URL +echo "PROJECT NAME:" $PROJECT_NAME +echo "PROJECT ID:" $2 +echo "MERGE IID:" $3 + +echo "\n------ Generating change marks --------" +docker container run --rm -v $(pwd):/tmp/ "$DOCKER_IMAGE" forgelib-changedocs -vv --outPath=/tmp/docs "$HOST_URL" "$2" "$PROJECT_NAME" "$3" +#docker container run --rm -v $(pwd):/tmp/ "$DOCKER_IMAGE" forgelib-changedocs -vv --combine --outPath=/tmp/docs --startdelimiter "/tmp/$4" --enddelimiter "/tmp/$5" "$HOST_URL" "$2" "$PROJECT_NAME" "$3" + +exit 0 + diff --git a/all/validate-all.sh b/all/validate-all.sh new file mode 100644 index 0000000..86ea8e9 --- /dev/null +++ b/all/validate-all.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# Copyright ETSI 2019-2021 +# See: https://forge.etsi.org/etsi-forge-copyright-statement.txt + +LOGFILE=openapi-validation.log +DOCKER_IMAGE=etsiforge/swagger-cli:4.0.3 + +echo -e "\n------ Switching to $1 folder --------" +cd $1 + +echo "------ Checking for previous logs ------" +if [ -f "$LOGFILE" ] ; then + echo "Found previous log. Removing it" + rm "$LOGFILE" +fi + +if [ -x "$(command -v docker)" ] ; then + RUN_IN_DOCKER=0 + echo "Using dockerized validator ($DOCKER_IMAGE)" + docker pull "$DOCKER_IMAGE" + #docker pull -q "$DOCKER_IMAGE" --> Pull quietly only from Ubuntu 20.04 +else + RUN_IN_DOCKER=1 + if [ ! -x "$(command -v swagger-cli)" ] ; then + echo "Validator swagger-cli not found. Quitting." + exit 1 + else + echo "Using local validator ($(which swagger-cli))" + fi +fi + +function validate { + echo -e "---- Validating $i: " + if [ $RUN_IN_DOCKER == 0 ] ; then + bname=$(basename "$1") + docker run --rm -v $(pwd):"/specs" $DOCKER_IMAGE swagger-cli validate "/specs/$bname" + else + swagger-cli validate "$1" + fi +} + +echo -e "\n------ Validating all YAML files (may takes several minutes) ------" +# If there are no YAML file, simply exit +ls | grep -q yaml +found_yaml=$? +if [ ! $found_yaml ] ; then + echo "-- No YAML files." + exit 0 +fi + +fres=0 +LOG="" +ERR="" +for i in *.yaml ; do + + MSG=$(validate "$i" 2>&1) + res=$? + if [ ! $res == 0 ] ; then + ERR="$ERR$MSG\n" + fi + LOG="$LOG$MSG\n" + fres=$(($fres||$res)) +done + +echo -e "\n-- Final validator returns $fres." | tee -a $LOGFILE +if [ $fres == 0 ] ; then + echo "No errors found, all files validate the OpenAPI definition. Below the complete log." | tee -a $LOGFILE +else + echo "Some errors found, see below the details." | tee -a $LOGFILE +fi + +if [ ! "$ERR" == "" ] ; then + echo -e "\n---- Errors detected ----" | tee -a $LOGFILE + echo -e $ERR | tee -a $LOGFILE +fi + +echo -e "\n---- Complete log of validation ----" | tee -a $LOGFILE +echo -e $LOG | tee -a $LOGFILE + +echo -e "\n------ Content of the folder ------" | tee -a $LOGFILE +ls | tee -a $LOGFILE + +# Exit code needed for jenkins to know the verdict of the build + +exit $fres -- GitLab From be43d8495d4a91ccba82324f32704b5b500c5721 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Mon, 17 Oct 2022 09:22:44 +0200 Subject: [PATCH 08/18] Generation config version stage Signed-off-by: Miguel Angel Reina Ortega --- all/.gitlab-ci.yml | 15 ++++++++++++ all/generate-config.sh | 55 ++++++++++++++++++++++++++++++++++++++++++ all/validate-all.sh | 2 +- 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 all/generate-config.sh diff --git a/all/.gitlab-ci.yml b/all/.gitlab-ci.yml index f3c7b6c..6384c27 100644 --- a/all/.gitlab-ci.yml +++ b/all/.gitlab-ci.yml @@ -35,6 +35,21 @@ Validate OpenAPI: paths: - ${LOGFILE_OPENAPI} +Generate config: + stage: generation + when: always + before_script: + - | + curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fgenerate-config%2Esh/raw?ref=master" >> generate-config.sh + - chmod +x generate-config.sh + script: + - echo 'Generate config' + - ./generate-config.sh $(pwd) + artifacts: + name: "$CI_JOB_NAME" + paths: + - api-versions.txt + CR contribution: stage: generation when: on_success diff --git a/all/generate-config.sh b/all/generate-config.sh new file mode 100644 index 0000000..882e6b5 --- /dev/null +++ b/all/generate-config.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright ETSI 2021 +# See: https://forge.etsi.org/etsi-forge-copyright-statement.txt +echo "------ Content of the folder ------" +ls + +# If there are no YAML file, simply exit +ls | grep -q yaml +found_yaml=$? +if [ ! $found_yaml ] ; then + echo "-- No YAML files." + exit 0 +fi + +echo "------ Installing necessary node modules -----" + +npm install js-yaml +npm install json + +pwd +echo "------ Removing old CONFIG file ------" +#rm -f api-versions.txt + +echo "------ Generating CONFIG file from all YAML files ------" + +echo "------ Switching to $1 folder --------" +#cd $1 +#pwd +fres=0 + +for i in $1/*.yaml ; do + echo "[$i]" + echo "[$i]" | grep -Po "TS[\w-]+\.yaml" | xargs -I % sh -c 'echo [%]' >> api-versions.txt ; + node ./node_modules/js-yaml/bin/js-yaml $i > "$i.json" ; + cat "$i.json" | node ./node_modules/json/lib/json info.version >> api-versions.txt + + input=$(cat "$i.json" | node ./node_modules/json/lib/json externalDocs.description) + pattern="[0-9]+[.][0-9]+[.][0-9]+" + if echo $input | grep -qPo $pattern + then + echo $input | grep -Po $pattern >> api-versions.txt + else + echo "-" >> api-versions.txt + fi + + # cat "$i.json" | node ./scripts/node_modules/json/lib/json externalDocs.description | grep -Po "[0-9]+[.][0-9]+[.][0-9]+" >> api-versions.txt + + cat "$i.json" | node ./node_modules/json/lib/json info.description | grep -Po "[0-9]{4}" >> api-versions.txt + res=$? + fres=$(($fres||$res)) +done + +# Exit code needed for jenkins to know the verdict of the build +echo "-- Final validator returns $fres." +exit $fres diff --git a/all/validate-all.sh b/all/validate-all.sh index 86ea8e9..4c37822 100644 --- a/all/validate-all.sh +++ b/all/validate-all.sh @@ -33,7 +33,7 @@ function validate { echo -e "---- Validating $i: " if [ $RUN_IN_DOCKER == 0 ] ; then bname=$(basename "$1") - docker run --rm -v $(pwd):"/specs" $DOCKER_IMAGE swagger-cli validate "/specs/$bname" + docker run --rm -v $(dirname $(realpath $1)):"/specs" $DOCKER_IMAGE swagger-cli validate "/specs/$bname" else swagger-cli validate "$1" fi -- GitLab From 4d1bffcfe67b11e70128a2dcfc24cbd27511a26e Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Wed, 19 Oct 2022 17:59:39 +0200 Subject: [PATCH 09/18] Printing file being validated Signed-off-by: Miguel Angel Reina Ortega --- all/validate-all.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/all/validate-all.sh b/all/validate-all.sh index 4c37822..19425e5 100644 --- a/all/validate-all.sh +++ b/all/validate-all.sh @@ -30,7 +30,6 @@ else fi function validate { - echo -e "---- Validating $i: " if [ $RUN_IN_DOCKER == 0 ] ; then bname=$(basename "$1") docker run --rm -v $(dirname $(realpath $1)):"/specs" $DOCKER_IMAGE swagger-cli validate "/specs/$bname" @@ -52,7 +51,7 @@ fres=0 LOG="" ERR="" for i in *.yaml ; do - + echo -e "---- Validating $i ... " MSG=$(validate "$i" 2>&1) res=$? if [ ! $res == 0 ] ; then -- GitLab From 49269a884e1e11bd6bd3532baf9bd1a68b2d6a3a Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Wed, 19 Oct 2022 19:10:34 +0200 Subject: [PATCH 10/18] Printing result of each file validation --- all/validate-all.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/all/validate-all.sh b/all/validate-all.sh index 19425e5..2b96deb 100644 --- a/all/validate-all.sh +++ b/all/validate-all.sh @@ -15,7 +15,7 @@ if [ -f "$LOGFILE" ] ; then fi if [ -x "$(command -v docker)" ] ; then - RUN_IN_DOCKER=0 + RUN_IN_DOCKER=1 echo "Using dockerized validator ($DOCKER_IMAGE)" docker pull "$DOCKER_IMAGE" #docker pull -q "$DOCKER_IMAGE" --> Pull quietly only from Ubuntu 20.04 @@ -53,6 +53,7 @@ ERR="" for i in *.yaml ; do echo -e "---- Validating $i ... " MSG=$(validate "$i" 2>&1) + echo "$MSG" res=$? if [ ! $res == 0 ] ; then ERR="$ERR$MSG\n" -- GitLab From 54b4f8e9a4d2eace94505b2f127123e180d599a4 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Thu, 20 Oct 2022 09:44:55 +0200 Subject: [PATCH 11/18] Moving validation loop into docker --- all/.gitlab-ci.yml | 7 +++--- all/validate-all-in-docker.sh | 47 +++++++++++++++++++++++++++++++++++ all/validate-all.sh | 2 +- 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 all/validate-all-in-docker.sh diff --git a/all/.gitlab-ci.yml b/all/.gitlab-ci.yml index 6384c27..8c8d3ca 100644 --- a/all/.gitlab-ci.yml +++ b/all/.gitlab-ci.yml @@ -25,11 +25,12 @@ Validate OpenAPI: stage: validation before_script: - | - curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fvalidate-all%2Esh/raw?ref=master" >> validate-all.sh - - chmod +x validate-all.sh + curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fvalidate-all-in-docker%2Esh/raw?ref=master" >> validate-all-in-docker.sh + - chmod +x validate-all-in-docker.sh script: - echo 'Validate OpenAPI' - - ./validate-all.sh $(pwd) + - docker run --rm -v $(pwd):"/specs" etsiforge/swagger-cli:4.0.3 /bin/sh -c "sh specs/validate-all-in-docker.sh" + #- ./validate-all.sh $(pwd) artifacts: name: "$CI_JOB_NAME" paths: diff --git a/all/validate-all-in-docker.sh b/all/validate-all-in-docker.sh new file mode 100644 index 0000000..b291d49 --- /dev/null +++ b/all/validate-all-in-docker.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# Copyright ETSI 2019-2021 +# See: https://forge.etsi.org/etsi-forge-copyright-statement.txt +LOGFILE=openapi-validation.log +echo -e "\n------ Validating all YAML files (may takes several minutes) ------" +# If there are no YAML file, simply exit +ls | grep -q yaml +found_yaml=$? +if [ ! $found_yaml ] +then + echo "-- No YAML files." + exit 0 +fi +fres=0 +LOG="" +ERR="" +for i in specs/*.yaml +do + #echo -e "---- Validating $i ... " + swagger-cli validate "$i" + #MSG=$(validate "$i" 2>&1) + #echo "$MSG" + res=$? + # if [ ! $res == 0 ] ; then + # ERR="$ERR$MSG\n" + # fi + # LOG="$LOG$MSG\n" + fres=$(($fres||$res)) +done +echo -e "\n-- Final validator returns $fres." | tee -a $LOGFILE +if [ $fres == 0 ] +then + echo "No errors found, all files validate the OpenAPI definition. Below the complete log." | tee -a $LOGFILE +else + echo "Some errors found, see below the details." | tee -a $LOGFILE +fi +if [ ! "$ERR" == "" ] +then + echo -e "\n---- Errors detected ----" | tee -a $LOGFILE + echo -e $ERR | tee -a $LOGFILE +fi +echo -e "\n---- Complete log of validation ----" | tee -a $LOGFILE +echo -e $LOG | tee -a $LOGFILE +#echo -e "\n------ Content of the folder ------" | tee -a $LOGFILE +#ls | tee -a $LOGFILE +# Exit code needed for jenkins to know the verdict of the build +exit $fres diff --git a/all/validate-all.sh b/all/validate-all.sh index 2b96deb..038fc4a 100644 --- a/all/validate-all.sh +++ b/all/validate-all.sh @@ -15,7 +15,7 @@ if [ -f "$LOGFILE" ] ; then fi if [ -x "$(command -v docker)" ] ; then - RUN_IN_DOCKER=1 + RUN_IN_DOCKER=0 echo "Using dockerized validator ($DOCKER_IMAGE)" docker pull "$DOCKER_IMAGE" #docker pull -q "$DOCKER_IMAGE" --> Pull quietly only from Ubuntu 20.04 -- GitLab From 1e9030c0fc5d2ba98c09c8214667d65d55e2f20d Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Thu, 20 Oct 2022 11:06:20 +0200 Subject: [PATCH 12/18] Moving generate config within validate stage --- all/.gitlab-ci.yml | 32 +++++++++++++++++++------------- all/generate-config.sh | 16 +--------------- all/validate-all-in-docker.sh | 15 ++++++++------- 3 files changed, 28 insertions(+), 35 deletions(-) diff --git a/all/.gitlab-ci.yml b/all/.gitlab-ci.yml index 8c8d3ca..e6be9e3 100644 --- a/all/.gitlab-ci.yml +++ b/all/.gitlab-ci.yml @@ -27,29 +27,35 @@ Validate OpenAPI: - | curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fvalidate-all-in-docker%2Esh/raw?ref=master" >> validate-all-in-docker.sh - chmod +x validate-all-in-docker.sh - script: - - echo 'Validate OpenAPI' - - docker run --rm -v $(pwd):"/specs" etsiforge/swagger-cli:4.0.3 /bin/sh -c "sh specs/validate-all-in-docker.sh" - #- ./validate-all.sh $(pwd) - artifacts: - name: "$CI_JOB_NAME" - paths: - - ${LOGFILE_OPENAPI} - -Generate config: - stage: generation - when: always - before_script: - | curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fgenerate-config%2Esh/raw?ref=master" >> generate-config.sh - chmod +x generate-config.sh script: + - echo 'Validate OpenAPI' + - docker run --rm -v $(pwd):"/specs" etsiforge/swagger-cli:4.0.3 /bin/sh -c "sh specs/validate-all-in-docker.sh" - echo 'Generate config' - ./generate-config.sh $(pwd) + #- ./validate-all.sh $(pwd) artifacts: name: "$CI_JOB_NAME" paths: + - ${LOGFILE_OPENAPI} - api-versions.txt + +# Generate config: + # stage: generation + # when: always + # before_script: + # - | + # curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fgenerate-config%2Esh/raw?ref=master" >> generate-config.sh + # - chmod +x generate-config.sh + # script: + # - echo 'Generate config' + # - ./generate-config.sh $(pwd) + # artifacts: + # name: "$CI_JOB_NAME" + # paths: + # - api-versions.txt CR contribution: stage: generation diff --git a/all/generate-config.sh b/all/generate-config.sh index 882e6b5..cfbfff3 100644 --- a/all/generate-config.sh +++ b/all/generate-config.sh @@ -1,9 +1,6 @@ #!/bin/bash # Copyright ETSI 2021 # See: https://forge.etsi.org/etsi-forge-copyright-statement.txt -echo "------ Content of the folder ------" -ls - # If there are no YAML file, simply exit ls | grep -q yaml found_yaml=$? @@ -17,18 +14,10 @@ echo "------ Installing necessary node modules -----" npm install js-yaml npm install json -pwd -echo "------ Removing old CONFIG file ------" -#rm -f api-versions.txt - echo "------ Generating CONFIG file from all YAML files ------" - -echo "------ Switching to $1 folder --------" -#cd $1 -#pwd fres=0 -for i in $1/*.yaml ; do +for i in *.yaml ; do echo "[$i]" echo "[$i]" | grep -Po "TS[\w-]+\.yaml" | xargs -I % sh -c 'echo [%]' >> api-versions.txt ; node ./node_modules/js-yaml/bin/js-yaml $i > "$i.json" ; @@ -49,7 +38,4 @@ for i in $1/*.yaml ; do res=$? fres=$(($fres||$res)) done - -# Exit code needed for jenkins to know the verdict of the build -echo "-- Final validator returns $fres." exit $fres diff --git a/all/validate-all-in-docker.sh b/all/validate-all-in-docker.sh index b291d49..ea4dd9f 100644 --- a/all/validate-all-in-docker.sh +++ b/all/validate-all-in-docker.sh @@ -17,14 +17,14 @@ ERR="" for i in specs/*.yaml do #echo -e "---- Validating $i ... " - swagger-cli validate "$i" + MSG=$(swagger-cli validate "$i" 2>&1) #MSG=$(validate "$i" 2>&1) - #echo "$MSG" + echo "$MSG" res=$? - # if [ ! $res == 0 ] ; then - # ERR="$ERR$MSG\n" - # fi - # LOG="$LOG$MSG\n" + if [ ! $res == 0 ] ; then + ERR="$ERR$MSG\n" + fi + LOG="$LOG$MSG\n" fres=$(($fres||$res)) done echo -e "\n-- Final validator returns $fres." | tee -a $LOGFILE @@ -43,5 +43,6 @@ echo -e "\n---- Complete log of validation ----" | tee -a $LOGFILE echo -e $LOG | tee -a $LOGFILE #echo -e "\n------ Content of the folder ------" | tee -a $LOGFILE #ls | tee -a $LOGFILE +mv $LOGFILE specs/ # Exit code needed for jenkins to know the verdict of the build -exit $fres +exit $fres \ No newline at end of file -- GitLab From dfa1758ed403d505160b6d1fa96149e0e67084e6 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Thu, 20 Oct 2022 11:28:29 +0200 Subject: [PATCH 13/18] Moving generate config back to generation stage --- all/.gitlab-ci.yml | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/all/.gitlab-ci.yml b/all/.gitlab-ci.yml index e6be9e3..d788105 100644 --- a/all/.gitlab-ci.yml +++ b/all/.gitlab-ci.yml @@ -27,35 +27,30 @@ Validate OpenAPI: - | curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fvalidate-all-in-docker%2Esh/raw?ref=master" >> validate-all-in-docker.sh - chmod +x validate-all-in-docker.sh - - | - curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fgenerate-config%2Esh/raw?ref=master" >> generate-config.sh - - chmod +x generate-config.sh script: - echo 'Validate OpenAPI' - docker run --rm -v $(pwd):"/specs" etsiforge/swagger-cli:4.0.3 /bin/sh -c "sh specs/validate-all-in-docker.sh" - echo 'Generate config' - - ./generate-config.sh $(pwd) #- ./validate-all.sh $(pwd) artifacts: name: "$CI_JOB_NAME" paths: - ${LOGFILE_OPENAPI} - - api-versions.txt -# Generate config: - # stage: generation - # when: always - # before_script: - # - | - # curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fgenerate-config%2Esh/raw?ref=master" >> generate-config.sh - # - chmod +x generate-config.sh - # script: - # - echo 'Generate config' - # - ./generate-config.sh $(pwd) - # artifacts: - # name: "$CI_JOB_NAME" - # paths: - # - api-versions.txt +Generate config: + stage: generation + when: always + before_script: + - | + curl "${CI_API_V4_URL}/projects/57/repository/files/all%2Fgenerate-config%2Esh/raw?ref=master" >> generate-config.sh + - chmod +x generate-config.sh + script: + - echo 'Generate config' + - ./generate-config.sh $ + artifacts: + name: "$CI_JOB_NAME" + paths: + - api-versions.txt CR contribution: stage: generation -- GitLab From 9c3e897e7a647f8233ea0b2a1bd1a04a4d822e21 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Thu, 20 Oct 2022 12:19:10 +0200 Subject: [PATCH 14/18] Adding quite mode for git clean Signed-off-by: Miguel Angel Reina Ortega --- all/.gitlab-ci.yml | 2 +- all/validate-all-in-docker.sh | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/all/.gitlab-ci.yml b/all/.gitlab-ci.yml index d788105..65f6755 100644 --- a/all/.gitlab-ci.yml +++ b/all/.gitlab-ci.yml @@ -16,6 +16,7 @@ workflow: variables: LOGFILE_OPENAPI: "openapi-validation.log" + GIT_CLEAN_FLAGS: -ffdxq stages: - validation @@ -30,7 +31,6 @@ Validate OpenAPI: script: - echo 'Validate OpenAPI' - docker run --rm -v $(pwd):"/specs" etsiforge/swagger-cli:4.0.3 /bin/sh -c "sh specs/validate-all-in-docker.sh" - - echo 'Generate config' #- ./validate-all.sh $(pwd) artifacts: name: "$CI_JOB_NAME" diff --git a/all/validate-all-in-docker.sh b/all/validate-all-in-docker.sh index ea4dd9f..eec5d0d 100644 --- a/all/validate-all-in-docker.sh +++ b/all/validate-all-in-docker.sh @@ -39,8 +39,12 @@ then echo -e "\n---- Errors detected ----" | tee -a $LOGFILE echo -e $ERR | tee -a $LOGFILE fi -echo -e "\n---- Complete log of validation ----" | tee -a $LOGFILE -echo -e $LOG | tee -a $LOGFILE + +echo -e "\n---- Complete log of validation ----" >> $LOGFILE +echo -e $LOG >> $LOGFILE + +# echo -e "\n---- Complete log of validation ----" | tee -a $LOGFILE +# echo -e $LOG | tee -a $LOGFILE #echo -e "\n------ Content of the folder ------" | tee -a $LOGFILE #ls | tee -a $LOGFILE mv $LOGFILE specs/ -- GitLab From 6e395bab81f6175b8f2d741d561bab8582502076 Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Thu, 20 Oct 2022 15:28:22 +0200 Subject: [PATCH 15/18] Improve generation of versions --- all/generate-config.sh | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/all/generate-config.sh b/all/generate-config.sh index cfbfff3..02b99ef 100644 --- a/all/generate-config.sh +++ b/all/generate-config.sh @@ -20,21 +20,24 @@ fres=0 for i in *.yaml ; do echo "[$i]" echo "[$i]" | grep -Po "TS[\w-]+\.yaml" | xargs -I % sh -c 'echo [%]' >> api-versions.txt ; - node ./node_modules/js-yaml/bin/js-yaml $i > "$i.json" ; - cat "$i.json" | node ./node_modules/json/lib/json info.version >> api-versions.txt + # node ./node_modules/js-yaml/bin/js-yaml $i > "$i.json" ; + # cat "$i.json" | node ./node_modules/json/lib/json info.version >> api-versions.txt - input=$(cat "$i.json" | node ./node_modules/json/lib/json externalDocs.description) - pattern="[0-9]+[.][0-9]+[.][0-9]+" - if echo $input | grep -qPo $pattern - then - echo $input | grep -Po $pattern >> api-versions.txt - else - echo "-" >> api-versions.txt - fi + # input=$(cat "$i.json" | node ./node_modules/json/lib/json externalDocs.description) + # pattern="[0-9]+[.][0-9]+[.][0-9]+" + # if echo $input | grep -qPo $pattern + # then + # echo $input | grep -Po $pattern >> api-versions.txt + # else + # echo "-" >> api-versions.txt + # fi - # cat "$i.json" | node ./scripts/node_modules/json/lib/json externalDocs.description | grep -Po "[0-9]+[.][0-9]+[.][0-9]+" >> api-versions.txt + # # cat "$i.json" | node ./scripts/node_modules/json/lib/json externalDocs.description | grep -Po "[0-9]+[.][0-9]+[.][0-9]+" >> api-versions.txt - cat "$i.json" | node ./node_modules/json/lib/json info.description | grep -Po "[0-9]{4}" >> api-versions.txt + # cat "$i.json" | node ./node_modules/json/lib/json info.description | grep -Po "[0-9]{4}" >> api-versions.txt + + + node ./node_modules/js-yaml/bin/js-yaml $i|node ./node_modules/json/lib/json info.version externalDocs.description info.description |grep -Po "[0-9]+[.][0-9]+[.][0-9]+|[0-9]{4}" >>api-versions.txt res=$? fres=$(($fres||$res)) done -- GitLab From cfc431c8904b9695ad1bc39724418bea7ff15dbe Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Thu, 20 Oct 2022 17:30:32 +0200 Subject: [PATCH 16/18] Using sed for generating versions Signed-off-by: Miguel Angel Reina Ortega --- all/generate-config.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/all/generate-config.sh b/all/generate-config.sh index 02b99ef..330b048 100644 --- a/all/generate-config.sh +++ b/all/generate-config.sh @@ -11,8 +11,8 @@ fi echo "------ Installing necessary node modules -----" -npm install js-yaml -npm install json +#npm install js-yaml +#npm install json echo "------ Generating CONFIG file from all YAML files ------" fres=0 @@ -36,9 +36,18 @@ for i in *.yaml ; do # cat "$i.json" | node ./node_modules/json/lib/json info.description | grep -Po "[0-9]{4}" >> api-versions.txt + #node ./node_modules/js-yaml/bin/js-yaml $i|node ./node_modules/json/lib/json info.version externalDocs.description info.description |grep -Po "[0-9]+[.][0-9]+[.][0-9]+|[0-9]{4}" >>api-versions.txt + FILE="${i}" + sed -n '/^info:/,/^[^[:space:]]/{/^ version:/p;/^[^([:space:]|info:)]/q}' ${FILE} | grep -Po '([0-9]+\.){2}[0-9]+' >> api-versions.txt #Info version + EXT_DOC_VERSION=`sed -n '/^externalDocs:/,/^[^[:space:]]/{/^ description:/,/^[^[:space:]]/p;/^[^([:space:]|externalDocs:)]/q}' ${FILE} | grep -Po '([0-9]+\.){2}[0-9]+'` # >> api-versions.txt # EXT_DOC_VERSION + if [ "$EXT_DOC_VERSION" == "" ]; then + echo "-" >>api-versions.txt + else + echo $EXT_DOC_VERSION >> api-versions.txt + fi + sed -n '/^info:/,/^[^[:space:]]/{/^ description:/,/^[^[:space:]]/p;/^[^([:space:]|info:)]/q}' ${FILE} | grep -Po '[0-9]{4}' >> api-versions.txt - node ./node_modules/js-yaml/bin/js-yaml $i|node ./node_modules/json/lib/json info.version externalDocs.description info.description |grep -Po "[0-9]+[.][0-9]+[.][0-9]+|[0-9]{4}" >>api-versions.txt - res=$? + res=$? fres=$(($fres||$res)) done exit $fres -- GitLab From f3c7362ec0340f4d75652f82034a51e1f6a9624a Mon Sep 17 00:00:00 2001 From: Miguel Angel Reina Ortega Date: Fri, 21 Oct 2022 14:14:22 +0200 Subject: [PATCH 17/18] Changes as suggested by Balazs Signed-off-by: Miguel Angel Reina Ortega --- sa5/.gitlab-ci.yml | 10 +++++----- sa5/sa5_delimiter_end.docx | Bin 23896 -> 23943 bytes sa5/sa5_delimiter_start.docx | Bin 23912 -> 23946 bytes 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sa5/.gitlab-ci.yml b/sa5/.gitlab-ci.yml index 3978428..424b09b 100644 --- a/sa5/.gitlab-ci.yml +++ b/sa5/.gitlab-ci.yml @@ -37,7 +37,7 @@ YANG Strict: after_script: - ls artifacts: - name: "$CI_JOB_NAME" + name: "YANG strict validation result" paths: - ${LOGFILE_YANG} @@ -51,7 +51,7 @@ YANG 3GPP Checks: - echo 'YANG 3GPP Checks' - ./lint-data-models.sh . artifacts: - name: "$CI_JOB_NAME" + name: "YANG 3gpp style check result" paths: - ${LOGFILE_LINT} @@ -65,11 +65,11 @@ Validate OpenAPI: - echo 'Validate OpenAPI' - ./validate-all.sh ./OpenAPI artifacts: - name: "$CI_JOB_NAME" + name: "OpenAPI validation result" paths: - ./OpenAPI/${LOGFILE_OPENAPI} -CR contribution: +Word CR text: stage: generation when: on_success only: @@ -89,4 +89,4 @@ CR contribution: artifacts: paths: - docs/ - expose_as: 'Word document contribution' \ No newline at end of file + expose_as: 'Word CR text' \ No newline at end of file diff --git a/sa5/sa5_delimiter_end.docx b/sa5/sa5_delimiter_end.docx index 7794450d118e31c05f1f0ac655d22dfa4dea2785..1e8210e0b75e4314214a21abc77bc44fea8c4d3b 100644 GIT binary patch delta 6016 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 KA)9SDNCg0{HgVhl delta 6042 zcmZqQ&3I!M;|4Ew&WFdoyq(9wz~DGJm|ds-wgGc6%ZVJm$(~OO?+I->aBHLPbQOh} z@%wduvRa&!DmoRHbmi5*Utd@1K7YM^xrw1!3-_r_6JN&MSmtPSMrqbsw`Y$JU#-lL za$2P0#CiI}i5j&-f6V@U?q7d9@yG`&)tM#?O2UV8``puXQth_rG$v0{Dx4T}W@dtS zWn*O4#;5g@l9F;I`*p6D<^0ut&LgaN;J!$zw8|MFKKoMVZi`z@8=2ljTDZkbTF!RZ zQff&)@0ty~Pv$YONbd5JK4mR+YI{hC?t*)s4g#UvE9<2$ai9FTTybaak_RR#>w87! zwOv^hd`r#Zv?tqa?_ZgjIjO`^SZh9G{pD}k5-ywL)m>P^Or2i2 zx+}AUol=@q5!iaj?b)pK!dbZI+K-NO?$paZZ24o3?D)A!|>q zm5OUrOzNl%tVak zn9!BWZ*QJr&}G~ckr@!za&moyTI((G8BE)k<($=gc#QX^mUdIi9F8uz1-l!j24!5{ zGiBx9ib-1`u z?@bSikaPOVF3bj(_}iAAXDdRiCpcW%=)~Qr%gBCg!f5My@+AXrB>U z_F~1}FVzoot_7RT(hS~eZWJ1QC+dfTvBrmlf)lduS>K6N*6%s+zkd!J!;0x0@07Oa zJ$DhS}}JpOae@%o?5cQXTcZt>6gEz$QqaoYdWWm5L*dtSy*p8dY~aq!1K zzn^_PuFibx&!ZG!meaTYw*CKpVi&uz>Q?>c)jxfTmDMzq{`Bc^s!OVA9eysOq%6(! zy}&MHdsv<9%Y~nIm4);is+VovWVT*XM>BkW{?=W==N70Y8zoN?*?Q{QOIbl7yD6)) zgj$lPx<+2E{aRDHK8i73zR!3=>9vhjXIqZ$IsBoMD^^?P>1uh8ss2Vk;)<&LR%9

g*EF+i)3vihC*C^o#kqH#Q{d@+>t)wp3(`Nmry;3JF!gqGQeQN0sPxzK zkBZVv|NoZy&po-&Lu4{r1m9)@o|#N6x3xa1Pd>}1U0?E^V?(mF&l{iF&g$EJe=~GV z=v8}RFe&HF_V--HSp~*3rf@TAf4h7>tNh`&cM6{p&i6d^S{G0vx~Rc(Rgm6x?JvKt zUry;{dfnmUxlSc|q4MSzd4Ip2&YhSur6|ZUjXA+%w#ck?0ng_68Ei92Zn~j;aAjav z?j6xkrqyTLg4?+3Q-fsM10&)x7i(-56WgO+H@$%>j%Wtcy7TnYjSn+D&y5kei?YUDUqxo*K*kg~&cA1ua zSG?6P`WGyn*>bYisL5i7X|zs9Zv*LUr z5*7wc^S?Z6QCLQLO3+V#sd{}|%b(%Pk2OC%JgxO`WEjF+Q8Z`zPW`PwLSFTh`{Cf5?1# z)w4NeM~f?@Z)7C!*XS=}-mubpbGJsJZ1|hnPG!lBzKg1rcKci@ZMN?6>-qAnxb?%~ z6?5}4{}gX|zD-r^-}@&_VW9zcmA20p{ya&LcW%&yCzaY$71vv8G=1VwINV&s{)eNp z{*nJvRqH8b`>!{?H_W*Eb1hfb5m{3Ooy$iAmh&)8_P^j6Vz=U8<+L9=(+%|G#P7>L zKB}y>_QS=ZrCY7`X#aV<)IMB;=e_vn{LRPhf6|G5~ zH`QlqNzA)b+x~uvtE+IUHR+!2Z+`J|eQ15yQTKe-OFK8dwx4XMFUp!`_oHI! z^*`pFFgqf^KjGwr3nz0g+chY0ujwq6@Jy)qy{?DfWSM00saBn^d;a^wcW0lM=ePO( zEks)F=pp|1O!pTzotV=3_R#;o*|xKO&f6HV#A14r-XCSte~&-?-d;H|U?NxM%8v|+ zK0z9rJ{V_*Hce2Je0t+fq1zUdqU84-PdxI>dICb~J?1Xb;Ak#dwngQN#EtycqjJ*w z4^4Eok6Km8c#hA)QRVQhOU|b`*0M+?+A>gXw zU4G@*iX9aany)4;JM8gTFVn2&il_QL--4AZ8jki}k%|7XdV5Fm-;Ke_4B9z2txwOi zWisx_=1F^$+yG9KHFM&8XDI0f&+5NCOG*5nU-yzv@}~d%s)|0X*Xw0J`#YEWwyi?d zhMgO?u74-Id-CtiD%O6jx{KRP&MNi=&FERV%=*JZlZZ1}C;qKwcvBg7KYYc8^p$^C zZ?&D@w~+PQ#Q3?g=lxIZS8H?Zzg*IBY;k|f{_kt17Myrc_Smt0p(S_TjmDT#O&<4MJ}Z=6F(mnOTS^# z`L5%ORp58tcPGv#E!nnR^bo&p`KqNGZ)dE}_13v_{G{lbRSV8_-?^jqO!qLCm8$y5 z*I^#L_lpBqo<4MJtA5J4Lr|#xXzVFX+bLz`*XF%8{I}`vs!v@<5Z z;z4Nq`mBZf<#wfByf#%Xshou2!(Ka07*UVGzBWan4fedTz};(!CwouMZMUlzI@Wk?ypBnFK2CBdq75GuJMU~Gq;}m)21-X z{##((<`Uudqt-J7@88~Lw>!2xNc@6^L4r*BMk9yip~g?5M3ynSPJPo_IqesJC|~ty z#n)?f%#YViD7|OqoZnd;ddgRQHPx06d z<79pR;E-yH74#`evzt@HfWrVutpw$*&Tc{xt+?>2@b>xpd~f z|Jmuz#?oIz{_r&Jy|$?Sw*C1}g>gS4`?Qmf&b=%UTI;0#>O$GQ-|cykzj|L?O%`wI z%w=xebftfhoZ#&Cpm#?WN+lfST`@=4fywI7@8s>%du4C`Z{y88ruk9*u!`RVn||I_Ilf_ z@a?aJZg`sV{L-{p%Jz4z&vA`!@9%AUeNSN7hHvTS**|%u0;gp)%-tKDs++(ie0=-9 zH3p*FU&r3&^R+&4{?@JP75hDYXk0j)(^=ng@0P>a9=9`h8fM8w`^kRmuvz~-V0+Ff zb^ZP?HcQTB$#L|}7hk^o?2na6yLh^I*$)3b-+y}Blx14{QG07{+`448Zg=p*hum8O zbOV?#nN3(*W_;T0)$X2IpUh{-ahcrO^PiRb-x-Ds=7^udKEGEds~2mwF^8P?k2)ik z61VbQQ2orCH5aECaMj;R%Gy3zN-W^Qi|GL?y|!;RJD0|DQ2ecb)b|Ug?HeS`qTh4v z`kZ}-Zv*=o<>&gTMeCjh|2$M)nQ48&rl!$vXL6~GlaW;KG^sDC9E*z&+BwbOzwfFc zWT-!9*?VP`XO+_yc|59M%yT^S$G~CYluI`b3rzo|c~tOzy`rAu#0e@QUyt|Bc`&n7 zX_CujkNTbuGah=pnfynx#hs^j>+C>tcU^@ug&IIYr5*EK@(qOe!$pp7%Id-9_-xGs7rFx#B}Q#|0nl%-CBwXPM@! zmB%aR6pEa@bHaJ;GQE!ag@y}S1lmpucooH{EmL&VU10b$7^eZd8*51Qq%C9?Jf zn>n_g<@Y>w@x>3xFZ^8wk9IN6l6R}=JI{RVPs^fz8wCCw+!q^DT)2i&fBvzukD`8)x27u%^LhnZ@-i3ThCbtux6wA*&#m0GY7oTzegPVNC?*dEao+xClIpo%|NusyZrSjOt z7cToIKltr`M6&#%j?0GgM=d7(U_7|BerevMMS{JZ@<%evkM$g{D0wu2m2;i$r%fz( zO&^~q|Cn=pTQ0Y7#l?G-+2{S6S_=ipn26hl1qqiU&C@3=ClL`5d@9SmJ3#>ynx7!do60Uq5YY z!mUs*^dP=jvh)wj^v<~g_oX-AP?emuQ|D`D*X?N^rz|$I{1|*^+nr|lEss9WsBAp@ zGOOjm?Y(icXD1fx$<9B+_+gEls!(A5R-yFi&)!v}T5S83y=Io={Zp~4pVp=n-#GW6 z$daj6ch#wwrDq#_{d3Dw zJ@e?&l1U+FKR8}B-fN#@zBxqs%SXAAj8p#Rw~oCOnRoju1G{Rq!#{;Lji*1o`(pGz zsm~)ibe8kfn7A5=N_I>-uAg+5}3-{le{?>G+L6V_S z(l=L;V}TFm$@!TWU9NxkvC{ag^~D!Hi`8e@U;ZQ9d)6c^quOH1YcJFIgByQdyilGS zx^?@en)*ZYCmd6_Vf@`SIHWzusc=f}#dwovS|xjaY?^LwUnOl)82;#nTpRlyHsdpQ zoq32!$oppz`TpCZ^4<1pT|Inpw{R5C+Ibu6Z6nSseNbA+ zSj+C8{PdYg|MPhzf30uGKm5N$uzRkC-?VwNExli*-xS*S>&2wqeCk(DE6ua~KlfJI zzwOs{|7QesyEaSe+R1TFHrRDzJ|hEz^5z6@WybpKI|c#{?;HQIFD%|WY3>Hk-tfj} z-7OMKg_$pxYFtWLyG~cqQ~LOSyG>4e_kZl^`h0zxqkh6%qpH@+tVcPv z7zDli%JqN6y2-{pbDl?iI+hXfkWt1iJ-(0Y;?qMB6&sc@zZSI+@wxSMQS`%GzxC9Q zbV^0N6KlMnSpPF8=X5Q{+gT+sIX|R4++I%F@?htad6NTYlx!A!KQ-vgsl4pj8WWlv zm~}JWd+hQ!Y5n@(ws)7CX8df=nJRDfLuBqGX-k?^`HJ3{>xhQ z#X_5LhG@`}xSwnhk$3;B%v=3?b<>&hXe{*qD*Wau%-Da1>B|q~R zgP%SBcr>-NH_~mhj%RaG5V|{~)a^}+=vo5Wjdu3Ii^X=m&n!S^FbIzAdTDHIL`UIm*exkE> zW!l`;*E{}P?)HSu$2Wc0wt#nf(ku7B7rr|zF?yV2`t|*!^LsnrOP+Q)#-*9?>ixkV z>0ka@8(j}-+$Pi0uG=#6S9bQ*Oo16CysE~vKHO)X1WiA)Xmxnwnc{hecGmltt8z&5 z95Ud0aIxux!t0gG7RHy`+`VO=JL}|?hsNJe#wFT&32B5L)Vc7`YvogmH|duqE$E!& z5*4PhheaxJN8yP%YY*&*$eqBx(%AX9$_ieiXyda%-G43ydNfV*w$lpzFeOrDTHNOl zZ{_0GcSAC4zguzMQe_F>&``2?=iT6(`m1FpMa4~fZaGBET5A&gnt9tX28Xv^ zo+HZU@xjrZ>vpJ_jolx$H^*Mv_VYyJn%;2k+4p|&R)za*wcFAk9=Fik-11Xez4MU;zAmi`mo027 zo*Sc6KUx3e)#YYKu5We^sQdZDXIfXMt!&(x=l7BpPq}iEolcr}}@>I0wbhPMsA_oh(_H(zW7wKssPO!LA)gk# z_s&!1xvyo#)ffLzd3EN*hyRQDSk=QW>~4K8ZE)?6@1|puD@-K!TeAM|TmA6prm&lD zuI*X7No%>~KR)YULgnl9=EU-AR^R)pFZ}M;uJ!fY86w}EYgYY!W!bjfuQ>j)JSYWj zeiwL?6=^v6LU;fp=VZkQeQD6h%@igE25D{v1|bGyuwim`gsOBJs2k11z#z&E>8&7C zluTY7VaI4O`Bj81;fGIO*Cqv&LxXa`2)$-U98j75_#N82#n zb(<_0g)IVeU|8eSYSqq|dW@}w9QEqE5>U|dAtgUKpeVnfSU<6# fVDiIgk;z|Tq!>3&=8tt?bqthe2Mm8Wnset+m&@qQJfCq|p6 z&(I66jg8g6{qxsbOW!TLPnFVc25evF6T3L_z#)rh-mlA#-(0#p+o^t%jtb}L7XkGP zo&J~oeJ&rry?Fxb>nUkL%r0tdw{0X|O`P)cfPss^#VH-DP53N?b2Qg8O_R#m*~6Tb zBgxNudyCIk?dLiRoDS64oiuZKp{iGr=gw_;v&oRj+D$-E?`84f4SsDUz55=@Hoq}; zC~&%Mf21-^|A5I|F6T#Yo=eI#hWdKU{gC2x-XqdOSbdE~ z&WiPwW*Tqxv#U#L18z*8eyd6C?Y7ppzu0Q0bxxS7n=ickP)!h@n5b#&{VHv@PTD zp?~wHs%wT6Z2lOz@FwTFt3^LT7=Cj+VB7Na@S>y&)x#XK-nseR*|b*6Z=&dvBfbf1 zrx|~^FjKaHBUNIq%f{6^q%yo!Iy+Wy%XWS-sb9X!^quP6&cJ=YB9!kGY&$0%^~dm5 zuCdVeA4Nq>t8-S|RTGylPLrD`qn0YglNT=eIAvmk`vp0vkR8j68tNAYd{|U>DP8q= zOtwYxm+XqwQ5!z6uD87Nny2W{NnMepk8jPh{=970q(jD@i>}D|`(FN1tsr|qI_8JL z72o1ZZ+&v=w~O5^7O~oUuj1AV-xrhC2v@GD+pioHcc*xd$0mWNq9W!ja?G5uURzE{ z9yxoZxA``sPt2+8*1mN4*B>fGO?&peu2_*|a=UX5i$LUshyV$10sq~}ix?xB_C#pD zus?WkpVukw=RbQ=gBDEXNLsN&u-~(3O2(AVyQK=NT8+dtJ?n+$KXF>iG|eFH?WMOB zlRepURYJJFe!LfOe9Mik9}Lea9Qa$u`Fs1O(mP&{76*HU%{iBU+a_XGa^di2OCI8(3W>ccYa8)dQgXRi45yZ3yZZM}@GjoiG?^)mzB9{2hD zU+V5%pRN8!zrNqS{QZ0rkNPk7es0_#xY_=84*#+l^%l2vmZ$sHurKvZ{j$67xk>Vx z8M*h?JiqOyTT{QS)NPsRyuU%4*UF@+KJI<=;pVL4Q?koTxnWSi7_LXGH$Kxv{$Jy!`&_^=J0~ zy11diUj0+||74@9$1cylz5D0$see9YrE*K1_`Nsr+M<-_2`xdzcV_!`?-UOd3i{_T zeadB>1vhrnQ`BWPqza^uin0uc#+GRE%o~T)D1nBbsMj~3X7cLeJtge ziteF_YcI2FsnkecH&k|PS*~$-+xmIypUq(T5&dApntdys1QV_HJc^V%5UyF`u`zJp zFF%8tNe9&@UEOFSs{BTEOWBo-Xamj2TWdB(&kilzvhZD1SKqn^n_jQ#4bR?rJIBCg zqu8m&YudkVthltIPV9ZM+voS|UjLu`QAc#M9?xi@{AiZ z&1RMq-QL2#fa9itWBbIE?)3T>nEl=*z z_1?MQn_J2mjn&)UwP`k9Et_rF$6cQ)B-5&*vwllpPc%2TT|ngmvAKnBEPAF%L^W(? zKWE^*vhdFhqZ3yrSnfNz+D=1?vB|v0L*8_+)Yb!Wq5LM&tW2S{muh5Q9y+aiY~muj zOv^r#x0Ayjd+aR{`pXhN%X`KhE#(!>(VGu9&Dy?q9z#U%^u1}7&-@PXh?};headaA zSNf2}ku)pDHzH}F&^-Uivld;;$WN*HHs9o5Tvg1^`To7^=i7C;Pv1?dE7@7Pb-kp} z?o)pQH|~9KX=>o%w&w!ws=2dXF0<~~Xfnem`^3Y=3^Fcp_Td>u8?OAjdP{C~ZbqZ? zllkBMo=pAJ->D+AVYb}G3Z97{zR%h!#3*@3&qk}>WbT7Wjc1p$x!4|P`q(JnJ!_+t zu|f9g+r^t2Q$vea#eST#hF3@O2J`*ymkc?NCVkQJ3OO!X9serBD|hmXc_-Ejo8}j& zU+kQCuXde4oy6Aby1Kt*-tNrpZ2fP&v#C^XMc%~Q=Q}GsSGM_SM*P_``P7B$G9r$Z zEE66&?qsfOajE~f{L>_P@7?!bANVe@<>j9+R@XOvQUcSmvsMJNHJ(&|(K3ZUt6<*I zx_6R2r=MQ_F3Guk#g;?vr$ev3`mpXp|MWjGiw#s-?$kw_E_2_v^!J_8G@H9W7Dh_t zzbnXW4xFB>`*~5yvL&aV?8~{W|Nd#a_!ak*uMUUWf7XZA2Of3Lzr?b0<7|6Sx@5KZ zrB*j(@;pI>$-ntH!O8N+kt63SCT*E~TdkJC^+X$|Rga4F@3*@T$=rF6X0TGfWlxg* z-!*08@80n%@qfE>!{?-`lDQ(+jufqvPs%#$_WzSO8<-$FmGkV>C*CDb#O|)&SHD|3 zNl$pC%yveFCB58dr)iY>9hZonR^<4$_r#3Au-rSm!Az^qswK;a*Pl|c;PQ+(2Tqp1 zZ3A{L7Yns0d*SZQqkG^cbG{)cSzZ7oOU}3lmEt123gzkcpWyBo~t8zWp8OlQaV~nYTxb&ElYQdfW`;MeareVBE^P)UOaJ2+n0}vFf6niT z`qTNso;Mzw*e?3`Liyo)+iX=PqaAlE0_ro)HF;N=&6g4=We7f2y-z3W*q)?>Yhl}; zr`Voe^=yvc(c(>J8oLA^mnMJ$VTfdg@|=47y3!EsLh|R9CUB_!S80@vd<^X zv0FQTo|>TJQqg;n=c3cEp5J{)JnmC==b;G#n)zbdmp|GrzUBP0*X;$LHvC(EOMlgmCv29tcEdTJjgublYXAM-ddU(CPxb0d@xK?s=B1}u$k-XzygWVM-u&y)wHNk=ynTA8 z_MwiROY|zQZRXRv@7vdloh~T6$iHW8#oDOCofe&SA3v|I|M&Q5;oa^;hOPgYVz&I< zrKvCeJMqP})uHk4To3;iUnQ*DV7*k@?tp*o=Byq6N?uG`nq_5oV(prz1yO>>6T46L z?uwBq**z~tM>;a=>gu}*KG(9gPhL9X-%Q;v#m8iQjY8$5F7lNfnJQ*_WI_F{I{n>s z->%iHH)r_1dGhW3vyS8jpRaPiUU{sf-z&Ua>^$driIS+Pi{2+T&Z^=I*!H~fWq9Aa zV|9$l{=r+;9k^5a=K9|gfAfnS_7xrQ`uOv9P0Qqd(TIEBl~?C~KK$;_iQ=T#Z?y;S z6kiB;-uhonKjqx(Q#U>}zOSr5uJkytCb~Z0-`w57#peR!?b}V2zqsX@UQhP*o056z z>s8;?Cikxi@C7_)3j2S^E&X4c%B=b~%YWoNRpajtzo5KN<7$k|^|=>RMYv2Pjz_NH zxsZ92ul3ndO^3MU)p`3`|2c;pzL(XJroHOyN_m&y6=g5h7U*kleCZO)yuNttRJo%L zWm|9a)YmjLT>IM+uXie{pyU6JeHZsMo-_7d!z<6mXS~j?YuW1FrE$`7FIS(E75()v zr2G3G(N^Ce#q19LId_XZmWNxc`*`McRq~gr8MA-J%KdUQ-F(7O>G2*}xsElj|E>Ca zcg^~#Z&=N3zc+?eH;BAAe(9jjVP;R&ts3oyUY94{-zv{n|5oP0^#|1+rYcKr+pqmp zCil~`w_mMmx2JR1SIN0cnqTd?&c8hM>Gn<2`|sgdT9_SresOfU=9{%rQU9mR^J@O@my#^@ zJ6!+jF7qbMwSSMkjjCz8Br;VdVg37*s|7DkANlw;CTvFcc1#|YBJ$`sJ zL~;VJ)ZxF(C%3L@Nqp*f`uX;F?_A^3awR#t2~67<*jscJPM2N2Yxb$T;7-xMYhLGK>@JJ@y_&k# z;qymEt*3rh3pq|^+PGz1c&^xUuBEo+$eHeCa=$q|o0QH6sFdyzkXKKw6ItZpmiZ{L zv?{6 znR*)xjxWqum-ukb8_t%ca(yf+9>OvojcxKbTokj+6E;$Jm2?uaUl4rO#;HhZf{c4p z%L2iQKL5EKt}}$6vi1p_cb)ly)#UVr6?<=d=Dwp=p3GnWl&|!lqE)aLhYm|$K+pp- z!wD>N`F%57m}EHru(;M-=a-$rZpXV|M}Ue_WJB8Vex|nYz4M(@7n(WTQ}PIG*^$?A z%}lwjq5trV`9USibV@YOF^f6!eJB(<#Wm%+j=EkSOWpylk~s=Wa;`U}T^t+AH!6IL zZTh6^(J8#pnAfOY%-SM|<%s)gm68?B?gEn(4oS)z9V#lBV^Hu(eZquFPB}-PzY=R( zH+*Ok*sd9IBH&%i0nMhe(!)rrJCirV+f0!>+wc0A-4>^B&W!xbxuCbHV&JG>wo)oy-zDVz$6|! zU!v?Ri+hm0%8u=4e2q;ObACL`vi4XDE9bnqDoKf5)!ln-T)#h1`4(HVb@Gw(TqSm% zZu25`sw8_hxd&{}aoM}HN7e9_^Cb>G|BNe{T=S+X657MJA5Cx z{HU9yu6Od{)aJGs4}Zrv{^99g@Zkafsn<%0aT%L8ODS5sH_!gOFX!E+$J2M3#F;F1 zJvDpnv_Fq-?QvM&b1bahE5-V8^v2+*JML!fZ+Y~lD_=0*v+iv39iAJm8EGk+$?{rUFSz=;op=0Zrq!|sVr8ntejT=;gXNYmgW7Md(LdCuDYl5 z`J9o}=@*gD&Kv#LN#5Kec~egB)2?Z6)o0xJlljCt^!h7}RoB!1XkVPcQtiJ#>-4Vx zP6hX+r~a)n9s~q4-Y8+U~05|fveH=C9m%v{KxU% zygTyI5zk#;?%atCvOhn)KyBIS1Eow(du{lNp4SK8Jon%7+bjRgA9aG|IC&NpZdu95 zz@WR?*IS9P-Z%e_f`G&OslVg}o>wut-(5Cs`il6KQAe|`SY%!Gc1=vWd?SHTI{kmG z;qJ0cfqYXZJWaf3bCBoh&D#45tqbC!Hy_M#HDpp=duiFt2d{tGSRXyXo;c;jnnvDx zjmOjfJnatRYu&=9H&^xmE3cgE`WyUE>PSoi(B*pf5Ko31CC zAK3h2PRxty_2LCG$FEjQx=>N)Ru?87{&Lk!v*7hA32|DHEV5P)LjV3O|GRYGkB~{J z`KNxpoxfj!+5fh;!2hMpg7s@2Po1{5fiL#xyW@;|o#Jz|16s8T7L;TJKjiWMyrcDQ z#@tVVl_EzM2-}4et}>Up@;f%f{B}lN`m7&+`EGH1Im?>ivZ{v3|100SFJD}K%y!Xv z_-0?pEtY^edzYFl)>${}lG57v?&7vnhbMe%XKzg^?*6Os>`eb;e)-qMXNqS%SCQ;K zReJWCYu&EzwkzuezO@JcZ#PUgO+K1kmNSR-x0sxL!9V`V2l+%;8$UX{YuGIB_nOf) z<-wueX7Li%wj~m*%=f+LN*f*2kf_+VY?jgMAIggb-E_t416DohiE`K3`N+pxnOi#c zdWQ0UE4Q~oZ^AaPY`b{poo7?vX1{1lM9ulCu>FtNTauN5vJ{*91>;6#IHMfN|YZHuioS* zQ67volXasV7^5cVMY}T2oV+F4hKa>}@~3DArfQGL4IUzsJz@l;;R&4?-F?23i(^!z r!2!y|z~IKgz#xFIj)8$eck-qfTgJzeKg2jNT1_^LHDq%L2Ppsm3;J{D delta 5589 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 Date: Fri, 21 Oct 2022 17:25:33 +0200 Subject: [PATCH 18/18] Fixing error with info.version in certain files Signed-off-by: Miguel Angel Reina Ortega --- all/.gitlab-ci.yml | 4 ++-- all/generate-config.sh | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/all/.gitlab-ci.yml b/all/.gitlab-ci.yml index 65f6755..b8c6c57 100644 --- a/all/.gitlab-ci.yml +++ b/all/.gitlab-ci.yml @@ -4,7 +4,8 @@ # - any (branch commit) # # GENERATION triggered by: -# - merge request +# - any (branch commit) for Generate config +# - merge request for CR contribution # workflow: @@ -31,7 +32,6 @@ Validate OpenAPI: script: - echo 'Validate OpenAPI' - docker run --rm -v $(pwd):"/specs" etsiforge/swagger-cli:4.0.3 /bin/sh -c "sh specs/validate-all-in-docker.sh" - #- ./validate-all.sh $(pwd) artifacts: name: "$CI_JOB_NAME" paths: diff --git a/all/generate-config.sh b/all/generate-config.sh index 330b048..93d0161 100644 --- a/all/generate-config.sh +++ b/all/generate-config.sh @@ -38,7 +38,12 @@ for i in *.yaml ; do #node ./node_modules/js-yaml/bin/js-yaml $i|node ./node_modules/json/lib/json info.version externalDocs.description info.description |grep -Po "[0-9]+[.][0-9]+[.][0-9]+|[0-9]{4}" >>api-versions.txt FILE="${i}" - sed -n '/^info:/,/^[^[:space:]]/{/^ version:/p;/^[^([:space:]|info:)]/q}' ${FILE} | grep -Po '([0-9]+\.){2}[0-9]+' >> api-versions.txt #Info version + INFO_VERSION=`sed -n '/^info:/,/^[^[:space:]]/{/^ version:/p;/^[^([:space:]|info:)]/q}' ${FILE} | grep -Po '([0-9]+\.){2}[0-9]+'` #>> api-versions.txt #Info version + if [ "$INFO_VERSION" == "" ]; then + echo "-" >>api-versions.txt + else + echo $INFO_VERSION >> api-versions.txt + fi EXT_DOC_VERSION=`sed -n '/^externalDocs:/,/^[^[:space:]]/{/^ description:/,/^[^[:space:]]/p;/^[^([:space:]|externalDocs:)]/q}' ${FILE} | grep -Po '([0-9]+\.){2}[0-9]+'` # >> api-versions.txt # EXT_DOC_VERSION if [ "$EXT_DOC_VERSION" == "" ]; then echo "-" >>api-versions.txt -- GitLab