From 498674f19ec503464dbf78dbe875fdc63027fd73 Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Tue, 3 Dec 2024 09:34:55 -0800 Subject: [PATCH 01/12] BUGFIX: app_name, not app-name so that input is actually used --- .github/workflows/finalize-template.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/finalize-template.yaml b/.github/workflows/finalize-template.yaml index e626546..6bd3030 100644 --- a/.github/workflows/finalize-template.yaml +++ b/.github/workflows/finalize-template.yaml @@ -3,7 +3,7 @@ name: Finalize Template on: workflow_dispatch: inputs: - app-name: + app_name: required: false description: > This is the name of your app; if left blank, it will match the From e11ceb0a6a8bcbba9439b299476bbaa100e27727 Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Tue, 3 Dec 2024 09:46:20 -0800 Subject: [PATCH 02/12] blacken app.template.py --- example_app/app.template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example_app/app.template.py b/example_app/app.template.py index b2e3118..bf4d541 100644 --- a/example_app/app.template.py +++ b/example_app/app.template.py @@ -9,7 +9,7 @@ @app.route("/", methods=("GET",)) def index(): print("Hello there") - return 'OK', 200 + return "OK", 200 APP_VERSION = None @@ -28,4 +28,4 @@ def status(): if __name__ == "__main__": - app.run(host='0.0.0.0', port=5000) + app.run(host="0.0.0.0", port=5000) From 2a0fe17f35f8118c7b0d724fb8663066718ad12f Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Tue, 3 Dec 2024 09:46:32 -0800 Subject: [PATCH 03/12] Set max line length for black + flake8 to 119 chars --- pyproject.template.toml | 3 +++ setup.cfg | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 setup.cfg diff --git a/pyproject.template.toml b/pyproject.template.toml index bce5cde..24f8e5c 100644 --- a/pyproject.template.toml +++ b/pyproject.template.toml @@ -23,3 +23,6 @@ priority = "explicit" [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.black] +line-length = 119 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..efd6c27 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[flake8] +# coordinated with Makefile MAX_LINE_LENGTH +max-line-length = 119 From 3a6fdf2f4d7d13a729a66eb269d9eb9ab6a1b76c Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Tue, 3 Dec 2024 15:16:23 -0800 Subject: [PATCH 04/12] Major updates to templates that may solve dareisay ALL the problems ... forever --- Dockerfile => Dockerfile.template | 9 ++-- README.md | 16 ++++---- example_app/app.template.py | 2 +- fingerprints.template.yaml | 23 ----------- kubernetes-config/README.template.md | 6 +-- kubernetes-config/automation.template.yaml | 6 +-- kubernetes-config/helm-release.template.yaml | 8 ++-- pyproject.template.toml | 2 +- scripts/finalize-template.py | 43 +++++++++----------- scripts/globals.template.sh | 33 --------------- tests/conftest.template.py | 2 +- 11 files changed, 44 insertions(+), 106 deletions(-) rename Dockerfile => Dockerfile.template (75%) delete mode 100644 fingerprints.template.yaml delete mode 100644 scripts/globals.template.sh diff --git a/Dockerfile b/Dockerfile.template similarity index 75% rename from Dockerfile rename to Dockerfile.template index e9c6a6e..e7a1f59 100644 --- a/Dockerfile +++ b/Dockerfile.template @@ -4,12 +4,9 @@ COPY poetry.lock pyproject.toml ./ RUN poetry install --no-dev --no-root --no-interaction FROM dependencies AS app -# If you change your app directory, you must also -# change the APP_MODULE here to match. Alternativel, -# you can also -# pass it into your build using `--build-arg` -# (see official docker documentation). -ARG APP_MODULE=example_app +# If you change your app directory to e.g., use src/ you MUST +# change the APP_MODULE here to match OR supply a --build-arg +ARG APP_MODULE=${template:app_name_underscore} ARG FLASK_PORT=5000 ENV FLASK_ENV=development \ PYTHONPATH=${APP_MODULE} \ diff --git a/README.md b/README.md index 6b06ca1..dc59d20 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ click the button above that says "Use this template" You will be asked to name your new repository. To take full advantage of the automation and kubernetes capabilities, you should create your new -repository under the "UWIT-IAM" namespace; this gives you access to +repository under the "UWIT-IAM" namespace; this gives you access to secrets that are consumable in your Github actions. Once you have done that, follow the instructions for @@ -22,12 +22,12 @@ Once you have done that, follow the instructions for If you are reading this, and you are not in the `flask-example` template repository, then you haven't yet finalized your template! -To finalize the template, visit your repository on GitHub, +To finalize the template, visit your repository on GitHub, then click on "Actions." Click the "Finalize Template" workflow, and click "Run this workflow." -A pull request will be generated for you to review and merge! This message will +A pull request will be generated for you to review and merge! This message will self-destruct after running that workflow. ## Updating the template @@ -37,15 +37,15 @@ This very basic templating engine does not allow for conditional logic. To use an argument name inside a document, make sure the document is named `. template.`, the final file name will be `.`. -You can use any supported argument with the format: `${template:}`; all -values are treated as strings. +You can use any supported argument with the format: `${template:}`; all +values are treated as strings. Functionally: ``` # foo.template.yaml -- policy-name: ${template:app_name}-policy +- policy-name: ${template:app_name_hyphen}-policy ``` becomes: @@ -60,8 +60,8 @@ becomes: ### About templating templates... Please note that `.template.` files are interpolated before any other templating -engine does anything; you may freely nest the `${template:}` syntax inside -other strings that other templating engines might use. +engine does anything; you may freely nest the `${template:}` syntax inside +other strings that other templating engines might use. ## Supported Values diff --git a/example_app/app.template.py b/example_app/app.template.py index bf4d541..ce1a15e 100644 --- a/example_app/app.template.py +++ b/example_app/app.template.py @@ -19,7 +19,7 @@ def index(): def status(): global APP_VERSION if APP_VERSION is None: - APP_VERSION = importlib_metadata.version("${template:app_name}") + APP_VERSION = importlib_metadata.version("${template:app_name_underscore}") deployment_id = os.environ.get("DEPLOYMENT_ID") status = 200 if deployment_id else 503 diff --git a/fingerprints.template.yaml b/fingerprints.template.yaml deleted file mode 100644 index 72ca842..0000000 --- a/fingerprints.template.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# This is the build configuration used by uw-it-build-fingerprinter. -# For more information, refer to the docs at: -# https://github.com/uwit-iam/fingerprinter - -release-target: app -docker: - repository: us-docker.pkg.dev/uwit-mci-iam/containers - app-name: ${template:app_name} - -targets: - dependencies: - include-paths: - - poetry.lock - - Dockerfile - app: - depends-on: [dependencies] - include-paths: - - example_app - - tests: - depends-on: [app] - include-paths: - - test diff --git a/kubernetes-config/README.template.md b/kubernetes-config/README.template.md index 638d422..51facdc 100644 --- a/kubernetes-config/README.template.md +++ b/kubernetes-config/README.template.md @@ -1,13 +1,13 @@ # Template Kubernetes Configuration -The basic kubernetes configuration provided here will subscribe you -to the [basic-web-service helm chart]. +The basic kubernetes configuration provided here will subscribe you +to the [basic-web-service helm chart]. After finalizing your template, you should copy the files in this directory into the [gcp-k8] repository, in the `dev/${template:app_name}` directory. Unless you change the values generated for you, your app will -expect to run at `https://${template:app_name}.iamdev.s.uw.edu`. +expect to run at `https://${template:app_name_hyphen}.iamdev.s.uw.edu`. [gcp-k8]: https://github.com/uwit-iam/gcp-k8 diff --git a/kubernetes-config/automation.template.yaml b/kubernetes-config/automation.template.yaml index f301141..ad9b3a1 100644 --- a/kubernetes-config/automation.template.yaml +++ b/kubernetes-config/automation.template.yaml @@ -4,11 +4,11 @@ apiVersion: image.toolkit.fluxcd.io/v1beta1 kind: ImagePolicy metadata: - name: ${template:app_name}-policy + name: ${template:app_name_hyphen}-policy namespace: default # must be 'default' in MCI, even if app itself is not in default spec: imageRepositoryRef: - name: ${template:app_name}-gar + name: ${template:app_name_hyphen}-gar filterTags: pattern: '^deploy-dev.(?P[0-9\.]+)\.v.+$' extract: '$ts' @@ -19,7 +19,7 @@ spec: apiVersion: image.toolkit.fluxcd.io/v1beta1 kind: ImageRepository metadata: - name: ${template:app_name}-gar + name: ${template:app_name_hyphen}-gar namespace: default # must be 'default' in MCI, even if app itself is not in default spec: image: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name} diff --git a/kubernetes-config/helm-release.template.yaml b/kubernetes-config/helm-release.template.yaml index 83d6e9c..285f6ba 100644 --- a/kubernetes-config/helm-release.template.yaml +++ b/kubernetes-config/helm-release.template.yaml @@ -9,12 +9,12 @@ apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: - name: ${template:app_name} + name: ${template:app_name_hyphen} namespace: default spec: values: app: - name: ${template:app_name} + name: ${template:app_name_hyphen} clusterDomain: iamdev.s.uw.edu replicaCount: 1 ports: @@ -45,8 +45,8 @@ spec: memory: "64M" cpu: "100m" image: - name: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name} - tag: latest # {"$imagepolicy": "default:${template:app_name}-policy:tag"} + name: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen} + tag: latest # {"$imagepolicy": "default:${template:app_name_underscore}-policy:tag"} chart: spec: diff --git a/pyproject.template.toml b/pyproject.template.toml index 24f8e5c..f2ee1bf 100644 --- a/pyproject.template.toml +++ b/pyproject.template.toml @@ -1,5 +1,5 @@ [tool.poetry] -name = "${template:app_name}" +name = "${template:app_name_underscore}" version = "0.1.0" description = "" authors = [] diff --git a/scripts/finalize-template.py b/scripts/finalize-template.py index 9383655..d3360b6 100644 --- a/scripts/finalize-template.py +++ b/scripts/finalize-template.py @@ -11,16 +11,14 @@ def get_parser(): "Fills out argument templates, then destroys, saves the new files," "and destroys all template files, including this script." ) - parser.add_argument('--app-name', required=True) - parser.add_argument('--maintainer', required=True) - parser.add_argument('--keepalive', required=False, default=False, action='store_true', dest='meta_keepalive') + parser.add_argument("--app-name", required=True) + parser.add_argument("--maintainer", required=True) + parser.add_argument("--keepalive", required=False, default=False, action="store_true", dest="meta_keepalive") return parser def get_template_files(): - return [ - str(path.joinpath()) for path in list(Path('.').rglob('*.template.*')) - ] + return [str(path.joinpath()) for path in list(Path(".").rglob("*.template.*"))] def finalize_template_file(path: str, args: Dict[str, Any]): @@ -28,26 +26,25 @@ def finalize_template_file(path: str, args: Dict[str, Any]): template = f.read() for key, val in args.items(): - template = template.replace( - f'${{template:{key}}}', str(val) - ) + template = template.replace(f"${{template:{key}}}", str(val)) - new_file_name = path.replace('.template', '') - with open(new_file_name, 'w') as f: + new_file_name = path.replace(".template", "") + with open(new_file_name, "w") as f: f.write(template) - logging.info( - f"Generated {new_file_name} from {path}" - ) + logging.info(f"Generated {new_file_name} from {path}") return new_file_name def main(): args = get_parser().parse_args() - values = { - k: v for k, v in vars(args).items() - if not k.startswith('meta_') - } + values = {k: v for k, v in vars(args).items() if not k.startswith("meta_")} + # add explicit values for only-hypen and only-underscore variants of the app name + # this is important because + # 1) Python package names cannot contain hyphens when importing ('django-utils' illegal; must be 'django_utils') + # 2) subdomains cannot contain underscores and we seed our application subdomains with the application name + values["app_name_hyphen"] = values["app_name"].replace("_", "-") + values["app_name_underscore"] = values["app_name"].replace("-", "_") logging.basicConfig(level=logging.INFO) logging.getLogger(__name__).setLevel(logging.INFO) @@ -58,16 +55,16 @@ def main(): for t in templates: finalize_template_file(t, values) if not args.meta_keepalive: - logging.info(f'Deleting template {t}') + logging.info(f"Deleting template {t}") os.remove(t) - os.system('poetry update') + os.system("poetry update") - logging.info('Deleting myself, too. My purpose is fulfilled. Byeeeeeeeeee!') + logging.info("Deleting myself, too. My purpose is fulfilled. Byeeeeeeeeee!") os.remove(__file__) - safe_app_name = args.app_name.replace("-", "_") - shutil.move("example_app", safe_app_name) + # this rename tied to Dockerfile.template + shutil.move("example_app", values["app_name_underscore"]) if __name__ == "__main__": diff --git a/scripts/globals.template.sh b/scripts/globals.template.sh deleted file mode 100644 index 6bd0893..0000000 --- a/scripts/globals.template.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -export APP_NAME="${template:app_name}" - -function get_instance_status { - local stage="$1" - # substitute '_' for '-' in APP_NAME - local url="https://${APP_NAME//_/-}.iam${stage}.s.uw.edu/status" - curl -sk "$url" || >&2 echo "Failed to check $url" -} - -function get_poetry_version { - grep 'version =' pyproject.toml | cut -f2 -d\" | head -n1 -} - - -function get_promotion_version { - # provides default values for the application version to deploy - # dev gets current version of app (presumed newest due to CI process) - # otherwise promotes dev => eval or eval => prod, depending on target stage - local target=$1 - case $target in - dev) - get_poetry_version - ;; - eval) - get_instance_status dev | jq -r .version - ;; - prod) - get_instance_status eval | jq -r .version - ;; - esac -} diff --git a/tests/conftest.template.py b/tests/conftest.template.py index f366329..5860b4a 100644 --- a/tests/conftest.template.py +++ b/tests/conftest.template.py @@ -1,5 +1,5 @@ import pytest -from ${template:app_name}.app import app as flask_app +from ${template:app_name_underscore}.app import app as flask_app @pytest.fixture From 96c5b4d45fd9ac3533c4c28325ccc725bbec98bf Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Tue, 3 Dec 2024 15:33:32 -0800 Subject: [PATCH 05/12] BUGFIX - imagepolicy is hyphenated --- kubernetes-config/helm-release.template.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes-config/helm-release.template.yaml b/kubernetes-config/helm-release.template.yaml index 285f6ba..658ae2a 100644 --- a/kubernetes-config/helm-release.template.yaml +++ b/kubernetes-config/helm-release.template.yaml @@ -46,7 +46,7 @@ spec: cpu: "100m" image: name: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen} - tag: latest # {"$imagepolicy": "default:${template:app_name_underscore}-policy:tag"} + tag: latest # {"$imagepolicy": "default:${template:app_name_hyphen}-policy:tag"} chart: spec: From d3320fa2215ff66295b0622f563a53401d83a1b2 Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Tue, 3 Dec 2024 15:34:17 -0800 Subject: [PATCH 06/12] Consistently hyphenate app in all docker-related urls --- .github/workflows/pull-request.template.yml | 8 ++++---- .github/workflows/release-on-push-to-main.template.yaml | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pull-request.template.yml b/.github/workflows/pull-request.template.yml index c10fcfd..a189976 100644 --- a/.github/workflows/pull-request.template.yml +++ b/.github/workflows/pull-request.template.yml @@ -71,7 +71,7 @@ jobs: file: ./Dockerfile push: true target: dependencies - tags: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name}.dependencies:${{ env.pr_tag }} + tags: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}.dependencies:${{ env.pr_tag }} secret-files: | "gcloud_auth_credentials=${{ steps.auth.outputs.credentials_file_path }}" @@ -82,7 +82,7 @@ jobs: file: ./Dockerfile push: true target: app - tags: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name}.app:${{ env.pr_tag }} + tags: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}.app:${{ env.pr_tag }} - name: Build and push Docker image (tests) uses: docker/build-push-action@v5 @@ -91,11 +91,11 @@ jobs: file: ./Dockerfile push: true target: tests - tags: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name}.tests:${{ env.pr_tag }} + tags: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}.tests:${{ env.pr_tag }} - uses: mshick/add-pr-comment@v2 env: - image: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name}.app:${{ env.pr_tag }} + image: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}.app:${{ env.pr_tag }} with: repo-token: ${{ secrets.GITHUB_TOKEN }} allow-repeats: false diff --git a/.github/workflows/release-on-push-to-main.template.yaml b/.github/workflows/release-on-push-to-main.template.yaml index 32ba63a..176bc00 100644 --- a/.github/workflows/release-on-push-to-main.template.yaml +++ b/.github/workflows/release-on-push-to-main.template.yaml @@ -65,8 +65,7 @@ jobs: push: true target: app tags: | - us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name}:${{ steps.get-version.outputs.version }} - us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name}:${{ env.DEPLOYMENT_ID }} + us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}:${{ steps.get-version.outputs.version }} + us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}:${{ env.DEPLOYMENT_ID }} secret-files: | "gcloud_auth_credentials=${{ steps.auth.outputs.credentials_file_path }}" - From f58692271746fbf6b462d3ba2ad1a10775820abb Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Tue, 3 Dec 2024 15:39:30 -0800 Subject: [PATCH 07/12] Update deploy template to not rely on fingerprinter --- .github/workflows/deploy.template.yml | 47 ++++++++++++++++++++------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/.github/workflows/deploy.template.yml b/.github/workflows/deploy.template.yml index 8f572e8..e14a9dd 100644 --- a/.github/workflows/deploy.template.yml +++ b/.github/workflows/deploy.template.yml @@ -51,19 +51,40 @@ jobs: - name: Install package run: poetry install - - name: Install jq for fingerprinter - run: sudo apt-get -y install jq - - name: Update env with promotion version that was provided if: github.event.inputs.version run: echo "target_version=${{ github.event.inputs.version }}" >> $GITHUB_ENV - name: Update env with promotion version if not provided if: '! env.target_version' + shell: bash run: | - source ./scripts/globals.sh - target_version=$(get_promotion_version ${{ github.event.inputs.cluster }}) - echo "target_version=${target_version}" >> $GITHUB_ENV + # $1 will be package name, $2 will be current version + set $(poetry version) + + case "${{ github.event.inputs.cluster }}" in + dev) + version="$2" + echo "Would set version to '$version' (from poetry version)" + ;; + eval) + # substitute '_' for '-' in APP_NAME + url="https://${1//_/-}.iamdev.s.uw.edu/status" + version=$(curl --silent $url | python -c "import json, sys; print(json.load(sys.stdin)['version'])") + echo "After consulting dev the eval version will be ${version}" + ;; + prod) + # substitute '_' for '-' in APP_NAME + url="https://${1//_/-}.iameval.s.uw.edu/status" + version=$(curl --silent $url | python -c "import json, sys; print(json.load(sys.stdin)['version'])") + echo "After consulting eval the prod version will be ${version}" + ;; + *) + echo "Invalid cluster! Pick one of dev|eval|prod" + exit 1 + ;; + esac + echo "target_version=${version}" >> $GITHUB_ENV - name: Auth to Google Cloud # important! this 'auth' is referenced as `steps.auth` on the next job @@ -80,10 +101,14 @@ jobs: run: |- echo '${{ steps.auth.outputs.access_token }}' | docker login -u oauth2accesstoken --password-stdin https://us-docker.pkg.dev - - name: Deploy version ${{ env.target_version }} + - name: Tag version ${{ env.target_version }} for ${{ github.event.inputs.cluster }} id: deploy run: | - echo "::notice::Deploying appid version ${{ env.target_version }} to ${{ github.event.inputs.cluster }}" - ./scripts/build.sh \ - --deploy ${{ inputs.cluster }} \ - -dversion ${{ env.target_version }} + # timestamp and deploy_tag are not DRY - see also release-on-push-to-main.yaml + timestamp=$(date --utc +%Y.%m.%d.%H.%M.%S) + deploy_tag="deploy-${{ github.event.inputs.cluster }}.${timestamp}.v${{ env.target_version }}" + echo "::notice::Deploying appid version ${{ env.target_version }} to ${{ github.event.inputs.cluster }} as ${deploy_tag}" + # this will create a new tag (deploy_tag) on an existing tag (env.target_version) + docker buildx imagetools create \ + --tag us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}:${deploy_tag} \ + us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}:${{ env.target_version }} From 01920718d7ffbced8ee28ea6713b21612be84177 Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Wed, 4 Dec 2024 08:41:39 -0800 Subject: [PATCH 08/12] Fix comments regarding max line length of 119 chars --- pyproject.template.toml | 1 + setup.cfg | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.template.toml b/pyproject.template.toml index f2ee1bf..e803ea4 100644 --- a/pyproject.template.toml +++ b/pyproject.template.toml @@ -25,4 +25,5 @@ requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.black] +# coordinated with setup.cfg max-line-length line-length = 119 diff --git a/setup.cfg b/setup.cfg index efd6c27..fa31184 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [flake8] -# coordinated with Makefile MAX_LINE_LENGTH +# coordinated with pyproject.toml MAX_LINE_LENGTH max-line-length = 119 From f7bf72963303170ea39507e9443bc94ae950def1 Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Wed, 4 Dec 2024 08:42:16 -0800 Subject: [PATCH 09/12] BUGFIX - do not require file suffix in template files (Dockerfile.template now processes correctly) --- scripts/finalize-template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/finalize-template.py b/scripts/finalize-template.py index d3360b6..7cad5da 100644 --- a/scripts/finalize-template.py +++ b/scripts/finalize-template.py @@ -18,7 +18,7 @@ def get_parser(): def get_template_files(): - return [str(path.joinpath()) for path in list(Path(".").rglob("*.template.*"))] + return [str(path.joinpath()) for path in list(Path(".").rglob("*.template*"))] def finalize_template_file(path: str, args: Dict[str, Any]): From b5e2556bb66d6e5909ccedf63dc8c90396422fe6 Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Wed, 4 Dec 2024 09:03:48 -0800 Subject: [PATCH 10/12] BUGFIX use consistent app_name_hyphen for all "image" definitions --- kubernetes-config/automation.template.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes-config/automation.template.yaml b/kubernetes-config/automation.template.yaml index ad9b3a1..fc9ceb9 100644 --- a/kubernetes-config/automation.template.yaml +++ b/kubernetes-config/automation.template.yaml @@ -22,7 +22,7 @@ metadata: name: ${template:app_name_hyphen}-gar namespace: default # must be 'default' in MCI, even if app itself is not in default spec: - image: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name} + image: us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen} interval: 2m0s secretRef: name: flux-mci-registry-credential From c4d4c4060d03e2be9e8a32e4e1c1e993c5c366b6 Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Wed, 4 Dec 2024 09:10:41 -0800 Subject: [PATCH 11/12] Strip DEPLOYMENT_ID from example-flask-app --- .github/workflows/deploy.template.yml | 3 ++- .../workflows/release-on-push-to-main.template.yaml | 6 ++---- Dockerfile.template | 4 +--- example_app/app.template.py | 11 ++++++----- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.github/workflows/deploy.template.yml b/.github/workflows/deploy.template.yml index e14a9dd..db3afd7 100644 --- a/.github/workflows/deploy.template.yml +++ b/.github/workflows/deploy.template.yml @@ -38,7 +38,8 @@ jobs: - name: Install and configure poetry run: | pipx install poetry - poetry config virtualenvs.create false + # PermissionERror in Python creating ... a directory?! + # poetry config virtualenvs.create false - if: github.event.inputs.cluster == 'prod' run: | diff --git a/.github/workflows/release-on-push-to-main.template.yaml b/.github/workflows/release-on-push-to-main.template.yaml index 176bc00..7926409 100644 --- a/.github/workflows/release-on-push-to-main.template.yaml +++ b/.github/workflows/release-on-push-to-main.template.yaml @@ -56,16 +56,14 @@ jobs: - name: Build and push Docker image uses: docker/build-push-action@v5 - env: - DEPLOYMENT_ID: deploy-dev.${{ steps.get-version.outputs.timestamp }}.v${{ steps.get-version.outputs.version }} with: - build-args: DEPLOYMENT_ID=${{ env.DEPLOYMENT_ID }} context: . file: ./Dockerfile push: true target: app tags: | us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}:${{ steps.get-version.outputs.version }} - us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}:${{ env.DEPLOYMENT_ID }} + us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}:deploy-dev.${{ steps.get-version.outputs.timestamp }}.v${{ steps.get-version.outputs.version }} + us-docker.pkg.dev/uwit-mci-iam/containers/${template:app_name_hyphen}:latest secret-files: | "gcloud_auth_credentials=${{ steps.auth.outputs.credentials_file_path }}" diff --git a/Dockerfile.template b/Dockerfile.template index 4a8d6f8..92bc25c 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -16,12 +16,10 @@ FROM dependencies AS app # If you change your app directory to e.g., use src/ you MUST # change the APP_MODULE here to match OR supply a --build-arg ARG APP_MODULE=${template:app_name_underscore} -ARG DEPLOYMENT_ID ARG FLASK_PORT=5000 ENV FLASK_ENV=development \ PYTHONPATH=${APP_MODULE} \ - FLASK_APP=${APP_MODULE}.app \ - DEPLOYMENT_ID=${DEPLOYMENT_ID} + FLASK_APP=${APP_MODULE}.app EXPOSE ${FLASK_PORT} COPY ${APP_MODULE}/ ./${APP_MODULE} # install root package now that we've copied it diff --git a/example_app/app.template.py b/example_app/app.template.py index ce1a15e..735bb5c 100644 --- a/example_app/app.template.py +++ b/example_app/app.template.py @@ -1,4 +1,3 @@ -import os import importlib.metadata as importlib_metadata # Python ^3.9 change from flask import Flask, jsonify @@ -19,12 +18,14 @@ def index(): def status(): global APP_VERSION if APP_VERSION is None: - APP_VERSION = importlib_metadata.version("${template:app_name_underscore}") + try: + APP_VERSION = importlib_metadata.version("${template:app_name_underscore}") + except importlib_metadata.PackageNotFoundError: + "Something went wrong locating the package that is this application. Was it installed via poetry?" - deployment_id = os.environ.get("DEPLOYMENT_ID") - status = 200 if deployment_id else 503 + status = 200 if APP_VERSION else 503 - return jsonify({"deployment_id": deployment_id, "version": APP_VERSION}), status + return jsonify({"version": APP_VERSION}), status if __name__ == "__main__": From 7b5cd3ff3b014b59207a1fc30d3746dc7e349f2f Mon Sep 17 00:00:00 2001 From: Mike Richards Date: Wed, 4 Dec 2024 10:03:47 -0800 Subject: [PATCH 12/12] Remove broken poetry config --- .github/workflows/deploy.template.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/deploy.template.yml b/.github/workflows/deploy.template.yml index db3afd7..64f46f4 100644 --- a/.github/workflows/deploy.template.yml +++ b/.github/workflows/deploy.template.yml @@ -38,8 +38,6 @@ jobs: - name: Install and configure poetry run: | pipx install poetry - # PermissionERror in Python creating ... a directory?! - # poetry config virtualenvs.create false - if: github.event.inputs.cluster == 'prod' run: |