From 1f0dff2352ee52962700bfcc800ca51322b7f0a5 Mon Sep 17 00:00:00 2001 From: Andrey Bogoroditskiy Date: Sat, 18 Mar 2023 23:55:59 +0500 Subject: [PATCH] feat: implemented tasks from lab 1 --- lab_1/scripts/build-client.sh | 70 ++++++++ lab_1/scripts/pipeline-18-03-2023.json | 121 ++++++++++++++ lab_1/scripts/pipeline.json | 126 ++++++++++++++ lab_1/scripts/quality-check.sh | 27 +++ lab_1/scripts/update-pipeline-definition.sh | 173 ++++++++++++++++++++ 5 files changed, 517 insertions(+) create mode 100644 lab_1/scripts/build-client.sh create mode 100644 lab_1/scripts/pipeline-18-03-2023.json create mode 100644 lab_1/scripts/pipeline.json create mode 100644 lab_1/scripts/quality-check.sh create mode 100644 lab_1/scripts/update-pipeline-definition.sh diff --git a/lab_1/scripts/build-client.sh b/lab_1/scripts/build-client.sh new file mode 100644 index 0000000..0dd5c8f --- /dev/null +++ b/lab_1/scripts/build-client.sh @@ -0,0 +1,70 @@ +#!/bin/bash - +#=============================================================================== +# +# FILE: build-client.sh +# +# USAGE: ./build-client.sh +# +# DESCRIPTION: +# +# OPTIONS: --- +# REQUIREMENTS: --- +# BUGS: --- +# NOTES: --- +# AUTHOR: YOUR NAME (), +# ORGANIZATION: +# CREATED: 03/13/2023 23:51 +# REVISION: --- +#=============================================================================== + +set -e +set -o pipefail + +echo "$PWD" + +SCRIPT_DIR=$PWD +#`dirname "$(readlink -f "$BASH_SOURCE")"` +ROOT_DIR=$PWD +#${SCRIPT_DIR%/*} +CLIENT_BUILD_DIR=$ROOT_DIR/dist +ENV_FILE_PATH=$ROOT_DIR/.env +PATH_TO_QUALITY_SCRIPT="$ROOT_DIR/quality-check.sh" + + + +echo "$ROOT_DIR" +echo "$SCRIPT_DIR" +echo "$CLIENT_BUILD_DIR" +echo "$(basename "../$CLIENT_BUILD_DIR")" + +currentBuildArchive=$ROOT_DIR/dist/client-app.zip + +if [ -e "$ENV_FILE_PATH" ]; then + # for testing environment variables from .env + export $(grep -v '^#' $ENV_FILE_PATH | xargs -d '\n') +else + echo ".env file is not found" +fi + +echo "$ENV_CONFIGURATION" + +if [ -e "$currentBuildArchive" ]; then + rm -rf "$currentBuildArvhive" + echo "Previous build $currentBuildArchive was successfully removed" +fi + +rm -rf $CLIENT_BUILD_DIR + +rm -rf node_modules + +npm cache clean --force + +npm i + +source "$PATH_TO_QUALITY_SCRIPT" + +npm run build --configuration=${ENV_CONFIGURATION:-"production"} --output-path=$CLIENT_BUILD_DIR + +zip -r $currentBuildArchive "$(basename "../$CLIENT_BUILD_DIR")" + +echo "The application was successfully build with $ENV_CONFIGURATION configuration." diff --git a/lab_1/scripts/pipeline-18-03-2023.json b/lab_1/scripts/pipeline-18-03-2023.json new file mode 100644 index 0000000..643c308 --- /dev/null +++ b/lab_1/scripts/pipeline-18-03-2023.json @@ -0,0 +1,121 @@ +{ + "pipeline": { + "name": "angular-shop", + "roleArn": "roleArn", + "artifactStore": { + "type": "S3", + "location": "codepipeline-artifactStore-location" + }, + "stages": [ + { + "name": "Source", + "actions": [ + { + "name": "Source", + "actionTypeId": { + "category": "Source", + "owner": "ThirdParty", + "provider": "GitHub", + "version": "1" + }, + "runOrder": 1, + "configuration": { + "Branch": "develop", + "OAuthToken": "****", + "Owner": "", + "PollForSourceChanges": true, + "Repo": "shop-angular-cloudfront" + }, + "outputArtifacts": [ + { + "name": "SourceArtifact" + } + ], + "inputArtifacts": [], + "region": "us-east-1", + "namespace": "SourceVariables" + } + ] + }, + { + "name": "QualityGate", + "actions": [ + { + "name": "LintingAntUnitTesting", + "actionTypeId": { + "category": "Build", + "owner": "AWS", + "provider": "CodeBuild", + "version": "1" + }, + "runOrder": 1, + "configuration": { + "EnvironmentVariables": "[{\"name\":\"BUILD_CONFIGURATION\",\"value\":\"\",\"type\":\"PLAINTEXT\"}]", + "ProjectName": "client-app-quality" + }, + "outputArtifacts": [], + "inputArtifacts": [ + { + "name": "SourceArtifact" + } + ], + "region": "us-east-1" + } + ] + }, + { + "name": "Approve", + "actions": [ + { + "name": "ManualApproval", + "actionTypeId": { + "category": "Approval", + "owner": "AWS", + "provider": "Manual", + "version": "1" + }, + "runOrder": 1, + "configuration": { + "CustomData": "Approve me" + }, + "outputArtifacts": [], + "inputArtifacts": [], + "region": "us-east-1" + } + ] + }, + { + "name": "Build", + "actions": [ + { + "name": "BuildAndDeploy", + "actionTypeId": { + "category": "Build", + "owner": "AWS", + "provider": "CodeBuild", + "version": "1" + }, + "runOrder": 1, + "configuration": { + "EnvironmentVariables": "[{\"name\":\"BUILD_CONFIGURATION\",\"value\":\"\",\"type\":\"PLAINTEXT\"}]", + "ProjectName": "client-app-build" + }, + "outputArtifacts": [ + { + "name": "BuildArtifact" + } + ], + "inputArtifacts": [ + { + "name": "SourceArtifact" + } + ], + "region": "us-east-1", + "namespace": "BuildVariables" + } + ] + } + ], + "version": 2 + } +} diff --git a/lab_1/scripts/pipeline.json b/lab_1/scripts/pipeline.json new file mode 100644 index 0000000..70d1297 --- /dev/null +++ b/lab_1/scripts/pipeline.json @@ -0,0 +1,126 @@ +{ + "pipeline": { + "name": "angular-shop", + "roleArn": "roleArn", + "artifactStore": { + "type": "S3", + "location": "codepipeline-artifactStore-location" + }, + "stages": [ + { + "name": "Source", + "actions": [ + { + "name": "Source", + "actionTypeId": { + "category": "Source", + "owner": "ThirdParty", + "provider": "GitHub", + "version": "1" + }, + "runOrder": 1, + "configuration": { + "Branch": "{{Branch name}}", + "OAuthToken": "****", + "Owner": "{{GitHub Owner}}", + "PollForSourceChanges": "{{PollForSourceChanges}}", + "Repo": "shop-angular-cloudfront" + }, + "outputArtifacts": [ + { + "name": "SourceArtifact" + } + ], + "inputArtifacts": [], + "region": "us-east-1", + "namespace": "SourceVariables" + } + ] + }, + { + "name": "QualityGate", + "actions": [ + { + "name": "LintingAntUnitTesting", + "actionTypeId": { + "category": "Build", + "owner": "AWS", + "provider": "CodeBuild", + "version": "1" + }, + "runOrder": 1, + "configuration": { + "EnvironmentVariables": "[{\"name\":\"BUILD_CONFIGURATION\",\"value\":\"{{BUILD_CONFIGURATION value}}\",\"type\":\"PLAINTEXT\"}]", + "ProjectName": "client-app-quality" + }, + "outputArtifacts": [], + "inputArtifacts": [ + { + "name": "SourceArtifact" + } + ], + "region": "us-east-1" + } + ] + }, + { + "name": "Approve", + "actions": [ + { + "name": "ManualApproval", + "actionTypeId": { + "category": "Approval", + "owner": "AWS", + "provider": "Manual", + "version": "1" + }, + "runOrder": 1, + "configuration": { + "CustomData": "Approve me" + }, + "outputArtifacts": [], + "inputArtifacts": [], + "region": "us-east-1" + } + ] + }, + { + "name": "Build", + "actions": [ + { + "name": "BuildAndDeploy", + "actionTypeId": { + "category": "Build", + "owner": "AWS", + "provider": "CodeBuild", + "version": "1" + }, + "runOrder": 1, + "configuration": { + "EnvironmentVariables": "[{\"name\":\"BUILD_CONFIGURATION\",\"value\":\"{{BUILD_CONFIGURATION value}}\",\"type\":\"PLAINTEXT\"}]", + "ProjectName": "client-app-build" + }, + "outputArtifacts": [ + { + "name": "BuildArtifact" + } + ], + "inputArtifacts": [ + { + "name": "SourceArtifact" + } + ], + "region": "us-east-1", + "namespace": "BuildVariables" + } + ] + } + ], + "version": 1 + }, + "metadata": { + "pipelineArn": "pipelineArn", + "created": 1586327944.749, + "updated": 1587023189.403 + } +} diff --git a/lab_1/scripts/quality-check.sh b/lab_1/scripts/quality-check.sh new file mode 100644 index 0000000..ef8d21f --- /dev/null +++ b/lab_1/scripts/quality-check.sh @@ -0,0 +1,27 @@ +#!/bin/bash - +#=============================================================================== +# +# FILE: quality-check.sh +# +# USAGE: ./quality-check.sh +# +# DESCRIPTION: +# +# OPTIONS: --- +# REQUIREMENTS: --- +# BUGS: --- +# NOTES: --- +# AUTHOR: YOUR NAME (), +# ORGANIZATION: +# CREATED: 03/14/2023 11:54 +# REVISION: --- +#=============================================================================== + +set -o nounset # Treat unset variables as an error +set -e +set -o pipefail + +npm run lint +npm run test +npm run e2e + diff --git a/lab_1/scripts/update-pipeline-definition.sh b/lab_1/scripts/update-pipeline-definition.sh new file mode 100644 index 0000000..b7e82d5 --- /dev/null +++ b/lab_1/scripts/update-pipeline-definition.sh @@ -0,0 +1,173 @@ +#!/bin/bash +#=============================================================================== +# +# FILE: update-pipeline-definition.sh +# +# USAGE: ./update-pipeline-definition.sh +# +# DESCRIPTION: +# +# OPTIONS: --- +# REQUIREMENTS: --- +# BUGS: --- +# NOTES: --- +# AUTHOR: YOUR NAME (), +# ORGANIZATION: +# CREATED: 03/15/2023 23:45 +# i REVISION: --- +#=============================================================================== + +defaultPipeline="pipeline" +customPipelineChoice="custom" +defaultBranchName="develop" + +# colors +red=$'\e[1;31m' +grn=$'\e[1;32m' +end=$'\e[0m' + +printColorfulString() { + local color=${2:-'\e[1;31m'}; + printf " ${color}${1}\n${end}" +} + +checkJQ() { + # jq test + type jq >/dev/null 2>&1 + exitCode=$? + + if [[ "$exitCode" -ne 0 ]]; then + printColorfulString "'jq' not found! (json parser)" + printf " Ubuntu Installation: sudo apt install jq\n" + printf " Redhat Installation: sudo yum install jq\n" + printColorfulString "Missing 'jq' dependency, exiting." + exit 1 + else + if [[ "$DEBUG" -eq 1 ]]; then + printColorfulString " 'jq' found!" $grn + fi + fi +} + +# perform checks: +checkJQ + +echo -n "Enter a CodePipeline name (or $customPipelineChoice)(default: $defaultPipeline): " +read -r pipelineName + +pipelineJson=${pipeline:-"./$defaultPipeline.json"}; + +if [[ ! -f $pipelineJson ]]; then + printColorfulString "$pipelineJson doesn't exists in current directory"; + exit 1; +fi + +echo -n "Which BUILD_CONFIGURATION name are you going to use (default: “”): " +read -r buildConfiguration +buildConfiguration=${buildConfiguration:-""}; + +echo -n "Enter a GitHub owner/account: " +read -r owner + +echo -n "Enter a source branch to use (default: $defaultBranchName): " +read -r branchName +branchName=${branchName:-$defaultBranchName}; + +echo -n "Do you want the pipeline to poll for changes (yes/no) (default: no)?: " +read -r shouldPollForChanges + +if [[ ! $shouldPollForChanges =~ ^(Yes|yes)$ ]]; then + shouldPollForChanges=true; +else + shouldPollForChanges=false; +fi + +echo -n "Do you want to save changes (yes/no) (default: yes)?: " +read -r shouldSaveUpdates +shouldSaveUpdates=${shouldSaveUpdates:-'Yes'}; + +if [[ ! $shouldSaveUpdates =~ ^(Yes|yes)$ ]]; then + echo "Exit"; + exit 0; +fi + +targetJson="pipeline-$(date +%d-%m-%Y).json"; + +cat "$pipelineJson" > "$targetJson"; + +deleteMetadata(){ + local metaData=$(jq '.metadata' "$1"); + if [[ $metaData == null ]]; then + printColorfulString "Error .metadata property doesn't exist in $1"; + exit 1; + else + jq 'del(.metadata)' "$1" > tmp.$$.json && mv tmp.$$.json "$1"; + fi +} + +updateVersion() { + local version=$(jq '.pipeline.version' "$1"); + if [[ $version == null ]]; then + printColorfulString "Unable to update version because .pipeline.version property doesn't exist in $1"; + exit 1; + else + jq '.pipeline.version += 1' "$1" > tmp.$$.json && mv tmp.$$.json "$1"; + fi +} + +updateSourceBranch(){ + local branch=$(jq '.pipeline.stages[0].actions[0].configuration.Branch' "$1"); + if [[ $branch == null ]]; then + printColorfulString "Unable to update branch because it property doesn't exist in $1"; + exit 1; + else + jq --arg branchName "$2" '.pipeline.stages[0].actions[0].configuration.Branch = $branchName' "$1" > tmp.$$.json && mv tmp.$$.json "$1"; + fi +} + + +updateOwner() { + local owner=$(jq '.pipeline.stages[0].actions[0].configuration.Owner' "$1"); + if [[ $owner == null ]]; then + printColorfulString "Unable to update owner because it property doesn't exist in $1"; + exit 1; + else + jq --arg owner "$2" '.pipeline.stages[0].actions[0].configuration.Owner = $owner' "$1" > tmp.$$.json && mv tmp.$$.json "$1"; + fi +} + +updatePollForSourceChanges(){ + local pollForSourceChanges=$(jq '.pipeline.stages[0].actions[0].configuration.PollForSourceChanges' "$1"); + if [[ $pollForSourceChanges == null ]]; then + printColorfulString "Unable to update poll for sources changes flag because it property doesn't exist in $1"; + exit 1; + else + jq --argjson pollForSourceChanges $2 '.pipeline.stages[0].actions[0].configuration.PollForSourceChanges = $pollForSourceChanges' "$1" > tmp.$$.json && mv tmp.$$.json "$1"; + fi +} + +updateEnvValue(){ + local firstEnv=$(jq '.pipeline.stages[1].actions[0].configuration.EnvironmentVariables' "$1"); + local secondEnv=$(jq '.pipeline.stages[3].actions[0].configuration.EnvironmentVariables' "$1"); + if [[ $firstEnv == null || $secondEnv == null ]]; then + printColorfulString "Unable to update env because it property doesn't exist in $1"; + exit 1; + else + jq --arg value "$2" '.pipeline.stages[].actions[].configuration.EnvironmentVariables |= (select(. != null) | sub("\"value\":\".*?\""; "\"value\":\"\($value)\""))' "$1" > tmp.$$.json && mv tmp.$$.json "$1"; + fi +} + +deleteMetadata $targetJson; + +updateVersion $targetJson; + +updateSourceBranch $targetJson $branchName; + +updateOwner $targetJson $owner; + +updatePollForSourceChanges $targetJson $shouldPollForChanges; + +updateEnvValue $targetJson $buildConfiguration; + +printColorfulString "Executed successfuly. Pipeline file: $targetJson" $grn; +exit 0;