From 867551c8081122a2c0211194f489eb416d8ba706 Mon Sep 17 00:00:00 2001 From: Simon Kok Date: Fri, 17 May 2024 13:23:31 +0200 Subject: [PATCH] Install: Add version checks and pre-deploy warnings (#726) **Why?** When you clone the ADF Github repository, it will not fetch the git tags. The installation docs describe that you should run `git fetch --tags` to retrieve those. However, if someone forgets to run that command, you run into a weird error that does not describe what is going wrong in a resolvable manner: > Error: Failed to create changeset for the stack: aws-deployment-framework, > Parameter validation failed: > Invalid length for parameter Tags[0].Value, value: 0, valid min length: 1 Additionally, if you installed ADF with the updated installer before. Then forget to fetch the latest git tags when you are about to deploy a new version of ADF, it will return a version number that is based on the old version instead of the new one. Making it hard to determine what version of ADF was installed. Long story short, the version in the `src/template.yml` should never be newer than the version determined via git tags. **What?** Added check to verify that the version number can be determined correctly. * If it did not return the version number, but an empty string instead: * it will test whether there is a .git folder. * If not, the user should clone a repository instead. * If the .git directory exists, it will instruct the user to fetch the git tags. * If a version number is returned, it will check whether the version number matches with the tag. * If it does, this means that it is building a released version of ADF. * If it does not, the user might not have switched to the right version tag yet. Hence, we warn the user to proceed with caution. Additionally, this change will add a warning when ADF gets deployed that the specific version and changes should be reviewed and tested in a non-production environment. Lastly, a check is added to ensure that the ADF version of the `src/template.yml` file should not be newer than the version resolved via git tags. If this is the case, it should instruct the user to fetch the latest tags from the ADF repository. --- .github/workflows/adf.yml | 6 ++ Makefile | 112 ++++++++++++++++++++++++++++++++++---- 2 files changed, 107 insertions(+), 11 deletions(-) diff --git a/.github/workflows/adf.yml b/.github/workflows/adf.yml index c2bb8516f..8afe36ef0 100644 --- a/.github/workflows/adf.yml +++ b/.github/workflows/adf.yml @@ -2,6 +2,9 @@ name: ADF CI on: [push, pull_request] +env: + CI_BUILD: 1 + jobs: build: runs-on: ubuntu-latest @@ -12,6 +15,9 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@v4 + with: + fetch-depth: 150 + fetch-tags: true - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: diff --git a/Makefile b/Makefile index 5395a39b8..ba818cfef 100644 --- a/Makefile +++ b/Makefile @@ -2,13 +2,13 @@ # SPDX-License-Identifier: Apache-2.0 # Makefile versions -MAKEFILE_VERSION := 2.1 +MAKEFILE_VERSION := 2.2 UPDATE_VERSION := make/latest # This Makefile requires Python version 3.9 or later REQUIRED_PYTHON_MAJOR_VERSION := 3 REQUIRED_PYTHON_MINOR_VERSION := 9 -PYTHON_EXECUTABLE := "python$(REQUIRED_PYTHON_MAJOR_VERSION)" +PYTHON_EXECUTABLE := python$(REQUIRED_PYTHON_MAJOR_VERSION) # Repository versions SRC_VERSION := $(shell git describe --tags --match 'v[0-9]*') @@ -18,9 +18,13 @@ SRC_VERSION_TAG_ONLY := $(shell git describe --tags --abbrev=0 --match 'v[0-9]*' SRC_URL_BASE := https://github.com/awslabs/aws-deployment-framework RAW_URL_BASE := https://raw.githubusercontent.com/awslabs/aws-deployment-framework -UPDATE_URL := "$(RAW_URL_BASE)/$(UPDATE_VERSION)/Makefile" -SRC_TAGGED_URL_BASE := "$(SRC_URL_BASE)/tree/$(SRC_VERSION_TAG_ONLY)" -MAKE_TAGGED_URL_BASE := "$(SRC_URL_BASE)/tree/make/$(MAKEFILE_VERSION)" +UPDATE_URL := $(RAW_URL_BASE)/$(UPDATE_VERSION)/Makefile +SRC_TAGGED_URL_BASE := $(SRC_URL_BASE)/tree/$(SRC_VERSION_TAG_ONLY) +MAKE_TAGGED_URL_BASE := $(SRC_URL_BASE)/tree/make/$(MAKEFILE_VERSION) +SRC_TAGGED_INSTALLATION_DOCS_URL := $(SRC_TAGGED_URL_BASE)/docs/installation-guide.md +MAKE_TAGGED_INSTALLATION_DOCS_URL := $(MAKE_TAGGED_URL_BASE)/docs/installation-guide.md +ISSUES_URL := $(SRC_URL_BASE)/issues +RELEASE_NOTES_URL := $(SRC_URL_BASE)/releases/tag/$(SRC_VERSION_TAG_ONLY) # Command line colors CLR_RED := $(shell printf "\033[0;31m") @@ -47,7 +51,8 @@ all: build # Which actions do not create an actual file like make expects: .PHONY: all clean update_makefile .PHONY: report_makefile_version report_versions version_report -.PHONY: build_debs deps src_deps docker version_number git_ignore docs tox +.PHONY: build_debs deps src_deps tox docker version_number git_ignore docs +.PHONY: verify_rooling verify_version .PHONY: pre_build pre_deps_build sam_build post_build build deps_build .PHONY: pre_deploy_msg pre_deploy sam_deploy post_deploy deploy @@ -171,8 +176,8 @@ docs: @echo "" @( \ echo "$(SRC_VERSION_TAG_ONLY)" | grep -E 'v[0-3]\.' &> /dev/null && \ - echo "* $(CLR_BLUE)$(MAKE_TAGGED_URL_BASE)/docs/installation-guide.md$(CLR_END)" || \ - echo "* $(CLR_BLUE)$(SRC_TAGGED_URL_BASE)/docs/installation-guide.md$(CLR_END)"; \ + echo "* $(CLR_BLUE)$(MAKE_TAGGED_INSTALLATION_DOCS_URL)$(CLR_END)" || \ + echo "* $(CLR_BLUE)$(SRC_TAGGED_INSTALLATION_DOCS_URL)$(CLR_END)"; \ ) @echo "" @echo "* $(CLR_BLUE)$(SRC_TAGGED_URL_BASE)/docs/admin-guide.md$(CLR_END)" @@ -222,7 +227,74 @@ verify_tooling: .venv ); \ ) -pre_build: build_deps docker version_number git_ignore +verify_version: .venv + @# If the version is empty and we are not in a CI build + @( \ + if [ "Z${SRC_VERSION}" = "Z" ] && [ "Z$${CI_BUILD}" = "Z" ]; then \ + echo '' && \ + echo '$(CLR_RED)Error: Unable to determine the ADF version!$(CLR_END)' && \ + if [ -e .git ]; then \ + echo '$(CLR_RED)The current directory is not a git clone of ADF.$(CLR_END)' && \ + echo '' && \ + echo '$(CLR_RED)Please read the installation guide to resolve this error:$(CLR_END)' && \ + echo '* $(CLR_BLUE)$(MAKE_TAGGED_INSTALLATION_DOCS_URL)$(CLR_END)' && \ + exit 1; \ + fi && \ + echo '$(CLR_RED)Most likely, the git tags have not been fetched yet.$(CLR_END)' && \ + echo '' && \ + echo '$(CLR_RED)Please fetch the git tags from the cloned repository to continue.$(CLR_END)' && \ + echo '$(CLR_RED)You can do this by running:$(CLR_END) git fetch --tags origin' && \ + echo '' && \ + exit 1; \ + fi \ + ) + @# If the src/template.yml version is newer than the git tagged version and + @# we are not in a CI build + @( \ + . .venv/bin/activate; \ + BASE_ADF_VERSION=$$(cat $(SRC_DIR)/template.yml | yq '.Metadata."AWS::ServerlessRepo::Application".SemanticVersion' -r); \ + [ "Z$${CI_BUILD}" != "Z" ] || \ + $(PYTHON_EXECUTABLE) -c "import sys; from packaging import version; version.parse(\"$$BASE_ADF_VERSION\") > version.parse(\"$(SRC_VERSION_TAG_ONLY)\") and sys.exit(1)" || \ + ( \ + echo '' && \ + echo '$(CLR_RED)Error: ADF Main template version is newer than the requested git tag version!$(CLR_END)' && \ + echo '$(CLR_RED)Most likely, the git tags have not been fetched recently yet.$(CLR_END)' && \ + echo '' && \ + echo '$(CLR_RED)Please fetch the git tags from the cloned repository to continue.$(CLR_END)' && \ + echo '$(CLR_RED)You can do this by running:$(CLR_END) git fetch --tags origin' && \ + echo '' && \ + echo "$(CLR_RED)ADF Main template version (src/template.yml):$(CLR_END) v$$BASE_ADF_VERSION" && \ + echo '$(CLR_RED)Resolved ADF version using git tags:$(CLR_END) $(SRC_VERSION_TAG_ONLY)' && \ + echo '' && \ + exit 1 \ + ) \ + ) + @# If the version number is not a release-tagged version and we are not in a CI build + @( \ + if [ "Z$(SRC_VERSION)" != "Z$(SRC_VERSION_TAG_ONLY)" ] && [ "Z$${CI_BUILD}" = "Z" ]; then \ + echo '' && \ + echo '$(CLR_RED)Caution: You are about to build the AWS Deployment Framework (ADF)$(CLR_END)' && \ + echo '$(CLR_RED)with commits that have not undergone the standard release testing process.$(CLR_END)' && \ + echo '' && \ + echo '$(CLR_RED)These untested commits may potentially cause issues or disruptions to your$(CLR_END)' && \ + echo '$(CLR_RED)existing ADF installation and deployment pipelines.$(CLR_END)' && \ + echo '$(CLR_RED)Please proceed with extreme caution and ensure you have appropriate backups$(CLR_END)' && \ + echo '$(CLR_RED)and contingency plans in place. It is highly recommended to thoroughly review$(CLR_END)' && \ + echo '$(CLR_RED)and test these commits in a non-production environment before you proceed.$(CLR_END)' && \ + echo '' && \ + echo 'ADF version base tag: $(CLR_RED)$(SRC_VERSION_TAG_ONLY)$(CLR_END)' && \ + echo 'ADF version of current commit: $(CLR_RED)$(SRC_VERSION)$(CLR_END)' && \ + echo '' && \ + echo 'Are you sure you want to continue? [y/N] ' && \ + read answer && \ + if [ "$${answer:-'N'}" != "Y" ] && [ "$${answer:-'N'}" != "y" ]; then \ + echo 'Aborting...' && \ + exit 1; \ + fi \ + fi \ + ) + +pre_build: build_deps docker version_number verify_version git_ignore pre_deps_build: deps docker version_number git_ignore @@ -250,13 +322,31 @@ pre_deploy_msg: @echo "" @echo "$(CLR_GREEN)Thank you for deploying ADF, we are about to proceed$(CLR_END)" @echo "" + @echo "$(CLR_RED)Caution:$(CLR_END) You are about to deploy ADF $(SRC_VERSION)." + @echo "Proceeding with the deployment will directly impact an existing ADF" + @echo "installation and ADF pipelines in this AWS Organization." + @echo "It is highly recommended to thoroughly review and test this version" + @echo "of ADF in a non-production environment before you proceed." + @echo "" + @echo "It is important to check the release notes prior to installing or updating." + @( \ + if [ "Z$(SRC_VERSION)" != "Z$(SRC_VERSION_TAG_ONLY)" ]; then \ + echo "Please read the local CHANGELOG.md file in the root of the repository."; \ + else \ + echo "Release notes of $(SRC_VERSION_TAG_ONLY) can be found at: $(CLR_BLUE)$(RELEASE_NOTES_URL)$(CLR_END)"; \ + fi \ + ) + @echo "" + @echo "Please also check whether there are known issues at: $(CLR_BLUE)$(ISSUES_URL)$(CLR_END)" + @echo "If you run into an issue, you can report these via GitHub issues." + @echo "" @echo "$(CLR_YELLOW)In the next step, a few questions need to be answered.$(CLR_END)" @echo "$(CLR_YELLOW)Please use the following guide to answer these:$(CLR_END)" @echo "" @( \ echo "$(SRC_VERSION_TAG_ONLY)" | grep -E 'v[0-3]\.' &> /dev/null && \ - echo "$(CLR_BLUE)$(MAKE_TAGGED_URL_BASE)/docs/installation-guide.md$(CLR_END)" || \ - echo "$(CLR_BLUE)$(SRC_TAGGED_URL_BASE)/docs/installation-guide.md$(CLR_END)"; \ + echo "$(CLR_BLUE)$(MAKE_TAGGED_INSTALLATION_DOCS_URL)$(CLR_END)" || \ + echo "$(CLR_BLUE)$(SRC_TAGGED_INSTALLATION_DOCS_URL)$(CLR_END)"; \ ) @echo "" @echo ""