diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index f486dacb..00000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint-env node */ -require("@rushstack/eslint-patch/modern-module-resolution"); - -module.exports = { - root: true, - extends: [ - "plugin:vue/vue3-essential", - "eslint:recommended", - "@vue/eslint-config-prettier", - ], - parserOptions: { - ecmaVersion: "latest", - }, - env: { - "vue/setup-compiler-macros": true, - node: true, - }, -}; diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml new file mode 100644 index 00000000..a08a2e3b --- /dev/null +++ b/.github/workflows/cicd.yml @@ -0,0 +1,194 @@ +# +# Example GitHub Actions config that drives UW-IT AXD2 integration and deployment +# +# Preconditions: +# +# 1) Application docker build is based on django-container +# +# 2) Application test suite is kicked off in docker/test.sh +# +# 3) Application repo has access to the two secrets +# at https://github.com/organizations/uw-it-aca/settings/secrets: +# +# GH_AUTH_TOKEN: Grants access to private flux deployment repo +# GCP_JSON_KEY: Grants access to Google Cloud Registry +# +# To adapt this config file to a specific django project: +# +# 1) Set RELEASE_NAME suitable for deployment to k8s. RELEASE_NAME must +# match the "repo" value in docker/*-values.yml. +# +# 2) Set DJANGO_APP to the name of the django project name/directory. +# +# 3) Verify that the lists of branches for push/pull_request is appropriate, +# and add other branch names if needed. Additional branch names must +# also have steps defined in the deploy job +# +# 4) Confirm that the build steps are suitable. Likely they are, but +# some projects have an intermediate build step that could benefit +# from caching, so it may be useful to augment the build steps. +# +--- +name: Build, Test and Deploy + +env: + RELEASE_NAME: django-vue + DJANGO_APP: app_name + +# Be sure that branches defined here have corresponding steps +# defined in the "deploy" job +on: + push: + branches: [main, master, qa, develop, feature/eval-me] + pull_request: + branches: [main, master, qa, develop, feature/eval-me] + types: [opened, reopened, synchronize] + +jobs: + context: + runs-on: ubuntu-22.04 + + outputs: + commit_hash: ${{ steps.context.outputs.commit_hash }} + git_repo_branch: ${{ steps.context.outputs.git_repo_branch }} + image_tag: ${{ steps.context.outputs.image_tag }} + + steps: + - name: Set up Context + id: context + uses: uw-it-aca/actions/cicd-context@main + with: + release_name: ${{ env.RELEASE_NAME }} + + build: + runs-on: ubuntu-22.04 + + needs: context + + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Run Python Linters + uses: uw-it-aca/actions/python-linters@main + with: + app_name: ${DJANGO_APP} + exclude_paths: "migrations" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Cache Docker layers + uses: actions/cache@v4 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-$(echo ${{ hashFiles('Dockerfile') }} | head -c 16) + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Build App Image + uses: docker/build-push-action@v6 + with: + context: . + target: app-container + tags: ${{ needs.context.outputs.image_tag }} + push: false + load: true + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache + + - name: Build Test Image + uses: docker/build-push-action@v6 + with: + target: app-test-container + tags: app-test-container + push: false + load: true + + - name: Run Tests in Image + id: tests + shell: bash + run: >- + docker run -u root -t + -v ${PWD}:/coverage + -e DJANGO_APP="$DJANGO_APP" + -e "ENV=localdev" -e "AUTH=SAML_MOCK" + app-test-container + bash -c ". ./docker/test.sh" + + - name: Record Test Results + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + python -m pip install --upgrade pip coverage coveralls==3.3.1 + coverage combine + coveralls + +# - name: Push Image to Repository +# if: github.event_name == 'push' +# uses: uw-it-aca/actions/gcr-push@main +# with: +# image_tag: ${{ needs.context.outputs.image_tag }} +# gcp_json_key: ${{ secrets.GCP_JSON_KEY }} +# +# deploy: +# if: github.event_name == 'push' +# +# needs: [context, build] +# +# outputs: +# context: ${{ steps.context.outputs.context }} +# +# runs-on: ubuntu-22.04 +# +# steps: +# - name: Checkout Repo +# uses: actions/checkout@v3 +# +# - name: Deployment Pipeline +# if: >- +# contains(fromJSON('["main", "master", "develop", "qa"]'), +# needs.context.outputs.git_repo_branch) +# uses: uw-it-aca/actions/cicd-deploy@main +# with: +# release_name: ${{ env.RELEASE_NAME }} +# commit_hash: ${{ needs.context.outputs.commit_hash }} +# git_repo_branch: ${{ needs.context.outputs.git_repo_branch }} +# gh_auth_token: ${{ secrets.GH_AUTH_TOKEN }} +# +# - name: Deploy Evaluation Branch +# if: needs.context.outputs.git_repo_branch == 'feature/eval-me' +# uses: uw-it-aca/actions/cicd-deploy@main +# with: +# release_name: ${{ env.RELEASE_NAME }} +# commit_hash: ${{ needs.context.outputs.commit_hash }} +# git_repo_branch: ${{ needs.context.outputs.git_repo_branch }} +# gh_auth_token: ${{ secrets.GH_AUTH_TOKEN }} +# app_instance: eval +# +# - name: 'Surface context from executed build step' +# id: context +# shell: bash +# run: echo "context=$(< ${CONTEXT_FILENAME})" >> $GITHUB_OUTPUT +# +# housekeeping: +# if: github.event_name == 'push' +# +# needs: [context, build, deploy] +# +# runs-on: ubuntu-22.04 +# +# steps: +# - name: House Keeping +# uses: uw-it-aca/actions/cicd-housekeeping@main +# with: +# release_name: ${{ env.RELEASE_NAME }} +# gh_auth_token: ${{ secrets.GH_AUTH_TOKEN }} +# registry_password: ${{ secrets.GCP_JSON_KEY }} +# context: ${{ needs.deploy.outputs.context }} diff --git a/.stylelintignore b/.stylelintignore deleted file mode 100644 index eeec074f..00000000 --- a/.stylelintignore +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore bundles for stylelinting -bundles/ \ No newline at end of file diff --git a/.stylelintrc b/.stylelintrc index 2691235a..e6c1776b 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -5,12 +5,6 @@ ], "rules": { "scss/no-global-function-names": null, - "no-invalid-position-at-import-rule": null, - "scss/at-import-partial-extension": [ - "never", - { - "severity": "warning" - } - ] + "no-invalid-position-at-import-rule": null } } diff --git a/.vscode/settings.json b/.vscode/settings.json index b2e240ce..47aaca3f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,7 @@ { - "black-formatter.args": ["--line-length=79"], - "autopep8.args": ["--max-line-length=79"], + "black-formatter.args": [ + "--line-length","79", + "--skip-string-normalization","true" + ], "stylelint.validate": ["vue", "scss"] } diff --git a/Dockerfile b/Dockerfile index a35dbc43..b65ca637 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,18 @@ -ARG DJANGO_CONTAINER_VERSION=2.0.1 +ARG DJANGO_CONTAINER_VERSION=2.0.6 FROM us-docker.pkg.dev/uwit-mci-axdd/containers/django-container:${DJANGO_CONTAINER_VERSION} as app-prebundler-container USER root -RUN apt-get update && apt-get install -y libpq-dev +RUN apt-get update && apt-get install libpq-dev -y USER acait ADD --chown=acait:acait . /app/ ADD --chown=acait:acait docker/ /app/project/ -# ADD --chown=acait:acait docker/app_start.sh /scripts -# RUN chmod u+x /scripts/app_start.sh +ADD --chown=acait:acait docker/app_start.sh /scripts +RUN chmod u+x /scripts/app_start.sh RUN /app/bin/pip install -r requirements.txt RUN /app/bin/pip install psycopg2 @@ -38,7 +38,7 @@ COPY --chown=acait:acait --from=node-bundler /app/app_name/static /app/app_name/ RUN /app/bin/python manage.py collectstatic --noinput -FROM us-docker.pkg.dev/uwit-mci-axdd/containers/django-container:${DJANGO_CONTAINER_VERSION} as app-test-container +FROM us-docker.pkg.dev/uwit-mci-axdd/containers/django-test-container:${DJANGO_CONTAINER_VERSION} AS app-test-container ENV NODE_PATH=/app/lib/node_modules COPY --from=app-container /app/ /app/ diff --git a/README.md b/README.md index deadb062..ecf1c5a8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # app_name -[](https://github.com/uw-it-aca/django-vue/actions) +[](https://github.com/uw-it-aca/django-vue/actions) [](https://coveralls.io/github/uw-it-aca/django-vue?branch=main) This is a template repository used for creating Django-Vue applications. Use this template to create a new project repository. diff --git a/app_name/apps.py b/app_name/apps.py index c086b8b0..ed6c2a7f 100644 --- a/app_name/apps.py +++ b/app_name/apps.py @@ -1,8 +1,12 @@ -# Copyright 2024 UW-IT, University of Washington +# Copyright 2025 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 from django.apps import AppConfig +from django.contrib.staticfiles.apps import StaticFilesConfig +class ViteStaticFilesConfig(StaticFilesConfig): + ignore_patterns = ['CVS', '*~'] + class AppNameConfig(AppConfig): name = "app_name" diff --git a/app_name/context_processors.py b/app_name/context_processors.py index 64894345..e9b12bd5 100644 --- a/app_name/context_processors.py +++ b/app_name/context_processors.py @@ -1,4 +1,4 @@ -# Copyright 2024 UW-IT, University of Washington +# Copyright 2025 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 from django.conf import settings diff --git a/app_name/models.py b/app_name/models.py index 844d86e6..59cb68aa 100644 --- a/app_name/models.py +++ b/app_name/models.py @@ -1,4 +1,4 @@ -# Copyright 2024 UW-IT, University of Washington +# Copyright 2025 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 from django.db import models diff --git a/app_name/templates/index.html b/app_name/templates/index.html index f7efe62f..bf0ca7a9 100644 --- a/app_name/templates/index.html +++ b/app_name/templates/index.html @@ -17,7 +17,7 @@
+ class="bg-body"> {% csrf_token %} diff --git a/app_name/templatetags/vite.py b/app_name/templatetags/vite.py index a566644d..2b6e2667 100644 --- a/app_name/templatetags/vite.py +++ b/app_name/templatetags/vite.py @@ -1,4 +1,4 @@ -# Copyright 2024 UW-IT, University of Washington +# Copyright 2025 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 import os @@ -17,8 +17,8 @@ def vite_manifest(entries_names): # updated to support Vite 5 (.vite/manifest.json output) manifest_filepath = getattr( settings, - "VITE_MANIFEST_PATH", - os.path.join(os.sep, "static", ".vite", "manifest.json"), + 'VITE_MANIFEST_PATH', + os.path.join(os.sep, 'static', '.vite', 'manifest.json'), ) with open(manifest_filepath) as fp: @@ -36,13 +36,13 @@ def _process_entries(names): chunk = manifest[name] import_scripts, import_styles = _process_entries( - chunk.get("imports", []) + chunk.get('imports', []) ) scripts += import_scripts styles += import_styles - scripts += [chunk["file"]] - styles += [css for css in chunk.get("css", [])] + scripts += [chunk['file']] + styles += [css for css in chunk.get('css', [])] _processed.add(name) @@ -51,9 +51,9 @@ def _process_entries(names): return _process_entries(entries_names) -@register.simple_tag(name="vite_styles") +@register.simple_tag(name='vite_styles') def vite_styles(*entries_names): - """ + ''' Populate an html template with styles generated by vite Usage:: @@ -65,19 +65,19 @@ def vite_styles(*entries_names): ... {% vite_styles 'main.js' 'other-entry.js' %} - """ + ''' _, styles = vite_manifest(entries_names) styles = map(lambda href: static(href), styles) def as_link_tag(href): return f'' - return mark_safe("\n".join(map(as_link_tag, styles))) + return mark_safe('\n'.join(map(as_link_tag, styles))) -@register.simple_tag(name="vite_scripts") +@register.simple_tag(name='vite_scripts') def vite_scripts(*entries_names): - """ + ''' Populate an html template with script tags generated by vite Usage:: @@ -89,11 +89,11 @@ def vite_scripts(*entries_names): {% vite_scripts 'main.js' 'other-entry.js' %}