Merge branch 'main' into nmb/pa11y-scanning

This commit is contained in:
Neil Martinsen-Burrell 2022-09-13 13:02:00 -05:00
commit 5bdd01138c
No known key found for this signature in database
GPG key ID: 6A3C818CC10D0184
26 changed files with 534 additions and 82 deletions

View file

@ -35,10 +35,10 @@ cf login -a api.fr.cloud.gov --sso
- [ ] Setup [commit signing in Github](#setting-up-commit-signing) and with git locally. - [ ] Setup [commit signing in Github](#setting-up-commit-signing) and with git locally.
### Steps for the onboarder ### Steps for the onboarder
- [ ] Add the onboardee to cloud.gov org and relevant spaces as a SpaceDeveloper - [ ] Add the onboardee to cloud.gov org (cisa-getgov-prototyping) and relevant spaces (unstable) as a SpaceDeveloper
```bash ```bash
cf set-space-role <cloud.account@email.gov> sandbox-gsa dotgov-poc SpaceDeveloper cf set-space-role <cloud.account@email.gov> cisa-getgov-prototyping unstable SpaceDeveloper
``` ```
- [ ] Add the onboardee to our login.gov sandbox team (`.gov registrar poc`) via the [dashboard](https://dashboard.int.identitysandbox.gov/) - [ ] Add the onboardee to our login.gov sandbox team (`.gov registrar poc`) via the [dashboard](https://dashboard.int.identitysandbox.gov/)

View file

@ -3,8 +3,7 @@ name: Build and deploy
# This workflow runs on pushes to main (typically, # This workflow runs on pushes to main (typically,
# a merged pull request) and on pushes of tagged commits. # a merged pull request) and on pushes of tagged commits.
# Pushes to main will deploy to Unstable; tagged commits # Pushes to main will deploy to Staging
# will deploy to Staging
on: on:
push: push:
@ -17,9 +16,9 @@ on:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
deploy-unstable: deploy-staging:
# if this job runs on a branch, we deduce that code # if this job runs on a branch, we deduce that code
# has been pushed to main and should be deployed to unstable # has been pushed to main and should be deployed to staging
if: ${{ github.ref_type == 'branch' }} if: ${{ github.ref_type == 'branch' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -30,13 +29,8 @@ jobs:
env: env:
DEPLOY_NOW: thanks DEPLOY_NOW: thanks
with: with:
cf_username: ${{ secrets.CF_USERNAME }} cf_username: ${{ secrets.CF_STAGING_USERNAME }}
cf_password: ${{ secrets.CF_PASSWORD }} cf_password: ${{ secrets.CF_STAGING_PASSWORD }}
cf_org: sandbox-gsa cf_org: cisa-getgov-prototyping
cf_space: dotgov-poc cf_space: staging
push_arguments: "-f ops/manifests/manifest-unstable.yaml" push_arguments: "-f ops/manifests/manifest-staging.yaml"
# deploy-staging:
# # if this job runs on a tag, we deduce that code
# # has been tagged for release and should be deployed to staging
# if: ${{ github.ref_type == 'tag' }}

View file

@ -3,7 +3,7 @@ name: Run Migrations
# This workflow can be run from the CLI # This workflow can be run from the CLI
# gh workflow run migrate.yaml -f environment=sandbox # gh workflow run migrate.yaml -f environment=sandbox
# OR # OR
# cf run-task getgov-unstable --wait \ # cf run-task getgov-staging --wait \
# --command 'python manage.py migrate' --name migrate # --command 'python manage.py migrate' --name migrate
on: on:
@ -13,22 +13,19 @@ on:
type: choice type: choice
description: Where should we run migrations description: Where should we run migrations
options: options:
- unstable
- staging - staging
jobs: jobs:
migrate-unstable: migrate-staging:
if: ${{ github.event.inputs.environment == 'unstable' }} if: ${{ github.event.inputs.environment == 'staging' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Run Django migrations for unstable - name: Run Django migrations for staging
uses: 18f/cg-deploy-action@main uses: 18f/cg-deploy-action@main
with: with:
cf_username: ${{ secrets.CF_USERNAME }} cf_username: ${{ secrets.CF_USERNAME }}
cf_password: ${{ secrets.CF_PASSWORD }} cf_password: ${{ secrets.CF_PASSWORD }}
cf_org: sandbox-gsa cf_org: cisa-getgov-prototyping
cf_space: dotgov-poc cf_space: staging
full_command: "cf run-task getgov-unstable --wait --command 'python manage.py migrate' --name migrate" full_command: "cf run-task getgov-staging --wait --command 'python manage.py migrate' --name migrate"
# migrate:
# if: ${{ github.event.inputs.environment == 'staging' }}

7
.gitignore vendored
View file

@ -2,6 +2,7 @@
docs/research/data/** docs/research/data/**
static/ static/
public/
credentials* credentials*
### The usual garbage files ### ### The usual garbage files ###
@ -148,3 +149,9 @@ cython_debug/
# Node # Node
node_modules node_modules
# Mac
.DS_Store
# Vim
*.swp

View file

@ -75,3 +75,13 @@ docker-compose run pa11y npm run pa11y-ci
The URLs that `pa11y-ci` will scan are configured in `src/.pa11yci`. When new The URLs that `pa11y-ci` will scan are configured in `src/.pa11yci`. When new
views and pages are added, their URLs should also be added to that file. views and pages are added, their URLs should also be added to that file.
## USWDS and styling
We use the U.S. Web Design System (USWDS) for building and styling our applications. Additionally, we utilize the [uswds-compile tool](https://designsystem.digital.gov/documentation/getting-started/developers/phase-two-compile/) from USWDS to compile and package the static assets.
When you run `docker-compose up` the `node` service in the container will begin to watch for changes in the `registrar/assets` folder, and will recompile once any changes are made.
Within the `registrar/assets` folder, the `_theme` folder contains three files initially generated by `uswds-compile`:
1. `_uswds-theme-custom-styles` contains all the custom styles created for this application
2. `_uswds-theme` contains all the custom theme settings (e.g. primary colors, fonts, banner color, etc..)
3. `styles.css` a entry point or index for the styles, forwards all of the other style files used in the project (i.e. the USWDS source code, the settings, and all custom stylesheets).
You can also compile the sass at any time using `npx gulp compile`. Similarly, you can copy over other static assets (images and javascript files), using `npx gulp copyAssets`.

View file

@ -28,8 +28,24 @@ cf target -o <ORG> -s <SPACE>
## Database ## Database
In sandbox, created with `cf create-service aws-rds micro-psql getgov-database`. In sandbox, created with `cf create-service aws-rds micro-psql getgov-ENV-database`.
Binding the database in `manifest-<ENVIRONMENT>.json` automatically inserts the connection string into the environment as `DATABASE_URL`. Binding the database in `manifest-<ENVIRONMENT>.json` automatically inserts the connection string into the environment as `DATABASE_URL`.
[Cloud.gov RDS documentation](https://cloud.gov/docs/services/relational-database/). [Cloud.gov RDS documentation](https://cloud.gov/docs/services/relational-database/).
# Deploy
We have two environments: `unstable` and `staging`. Developers can deploy locally to unstable whenever they want. However, only our CD service can deploy to `staging`, and it does so on every commit to `main`. This is to ensure that we have a "golden" environment to point to, and can still test things out in an unstable space. To deploy locally to `unstable`:
```bash
cf target -o cisa-getgov-prototyping -s unstable
cf push getgov-unstable -f ops/manifests/manifest-unstable.yaml
cf run-task getgov-unstable --command 'python manage.py migrate' --name migrate
```
## Serving static assets
We are using [WhiteNoise](http://whitenoise.evans.io/en/stable/index.html) plugin to serve our static assets on cloud.gov. This plugin is added to the `MIDDLEWARE` list in our apps `settings.py`.
Note that its a good idea to run `collectstatic` locally or in the docker container before pushing files up to `unstable`. This is because `collectstatic` relies on timestamps when deciding to whether to overwrite the existing assets in `/public`. Due the way files are uploaded, the compiled css in the `/assets/css` folder on `unstable` will have a slightly earlier timestamp than the files in `/public/css`, and consequently running `collectstatic` on`unstable` will not update `public/css` as you may expect.

View file

@ -27,7 +27,7 @@ To rotate secrets, create a new `credentials-<ENVIRONMENT>.json` file, upload it
Example: Example:
```bash ```bash
cf uups getgov-credentials -p credentials-unstable.json cf cups getgov-credentials -p credentials-unstable.json
cf restage getgov-unstable --strategy rolling cf restage getgov-unstable --strategy rolling
``` ```

View file

@ -0,0 +1,23 @@
---
applications:
- name: getgov-staging
buildpacks:
- python_buildpack
path: ../../src
instances: 1
memory: 512M
stack: cflinuxfs3
timeout: 180
command: gunicorn registrar.config.wsgi -t 60
health-check-type: http
health-check-http-endpoint: /health
env:
# Send stdout and stderr straight to the terminal without buffering
PYTHONUNBUFFERED: yup
# Tell Django where to find its configuration
DJANGO_SETTINGS_MODULE: registrar.config.settings
routes:
- route: getgov-staging.app.cloud.gov
services:
- getgov-credentials
- getgov-staging-database

View file

@ -8,7 +8,7 @@ applications:
memory: 512M memory: 512M
stack: cflinuxfs3 stack: cflinuxfs3
timeout: 180 timeout: 180
command: gunicorn registrar.config.wsgi -t 60 command: ./run.sh
health-check-type: http health-check-type: http
health-check-http-endpoint: /health health-check-http-endpoint: /health
env: env:
@ -20,4 +20,4 @@ applications:
- route: getgov-unstable.app.cloud.gov - route: getgov-unstable.app.cloud.gov
services: services:
- getgov-credentials - getgov-credentials
- getgov-database - getgov-unstable-database

View file

@ -1,11 +1,16 @@
# NOTE: This script does not work with cf v8. We recommend using cf v7 for all cloud.gov commands. # NOTE: This script does not work with cf v8. We recommend using cf v7 for all cloud.gov commands.
if [ ! $(command -v gh) ] || [ ! $(command -v jq) ] || [ ! $(command -v cf) ]; then if [ ! $(command -v gh) ] || [ ! $(command -v jq) ] || [ ! $(command -v cf) ]; then
echo "jq, cf, and gh packages must be installed. Please install via your preferred manager." echo "jq, cf, and gh packages must be installed. Please install via your preferred manager."
exit 1 exit 1
fi fi
cf spaces if [ -z "$1" ]; then
read -p "Are you logged in to the dotgov-poc CF space above? (y/n) " -n 1 -r echo 'Please specify a space to target (i.e. unstable, staging)' >&2
exit 1
fi
cf target -o cisa-getgov-prototyping -s $1
read -p "Are you logged in to the cisa-getgov-prototyping CF org above and targeting the correct space? (y/n) " -n 1 -r
echo echo
if [[ ! $REPLY =~ ^[Yy]$ ]] if [[ ! $REPLY =~ ^[Yy]$ ]]
then then
@ -13,7 +18,7 @@ then
fi fi
gh auth status gh auth status
read -p "Are you logged into a Github account with access to cisagov/dotgov? (y/n) " -n 1 -r read -p "Are you logged into a Github account with access to cisagov/getgov? (y/n) " -n 1 -r
echo echo
if [[ ! $REPLY =~ ^[Yy]$ ]] if [[ ! $REPLY =~ ^[Yy]$ ]]
then then
@ -21,6 +26,7 @@ then
fi fi
echo "Great, removing and replacing Github CD account..." echo "Great, removing and replacing Github CD account..."
cf target -s $1
cf delete-service-key github-cd-account github-cd-key cf delete-service-key github-cd-account github-cd-key
cf create-service-key github-cd-account github-cd-key cf create-service-key github-cd-account github-cd-key
cf service-key github-cd-account github-cd-key cf service-key github-cd-account github-cd-key
@ -31,8 +37,9 @@ then
exit 1 exit 1
fi fi
upcase_space=$(printf "%s" "$1" | tr '[:lower:]' '[:upper:]')
cf service-key github-cd-account github-cd-key | sed 1,2d | jq -r '[.username, .password]|@tsv' | cf service-key github-cd-account github-cd-key | sed 1,2d | jq -r '[.username, .password]|@tsv' |
while read -r username password; do while read -r username password; do
gh secret --repo cisagov/dotgov set CF_USERNAME --body $username gh secret --repo cisagov/getgov set CF_${upcase_space}_USERNAME --body $username
gh secret --repo cisagov/dotgov set CF_PASSWORD --body $password gh secret --repo cisagov/getgov set CF_${upcase_space}_PASSWORD --body $password
done done

View file

@ -11,6 +11,7 @@ django-csp = "*"
environs = {extras=["django"]} environs = {extras=["django"]}
gunicorn = "*" gunicorn = "*"
psycopg2-binary = "*" psycopg2-binary = "*"
whitenoise = "*"
[dev-packages] [dev-packages]
django-debug-toolbar = "*" django-debug-toolbar = "*"
@ -19,4 +20,4 @@ bandit = "*"
black = "*" black = "*"
flake8 = "*" flake8 = "*"
mypy = "*" mypy = "*"
types-requests = "*" types-requests = "*"

28
src/Pipfile.lock generated
View file

@ -46,11 +46,11 @@
}, },
"django": { "django": {
"hashes": [ "hashes": [
"sha256:031ccb717782f6af83a0063a1957686e87cb4581ea61b47b3e9addf60687989a", "sha256:a153ffd5143bf26a877bfae2f4ec736ebd8924a46600ca089ad96b54a1d4e28e",
"sha256:032f8a6fc7cf05ccd1214e4a2e21dfcd6a23b9d575c6573cacc8c67828dbe642" "sha256:acb21fac9275f9972d81c7caf5761a89ec3ea25fe74545dd26b8a48cb3a0203e"
], ],
"index": "pypi", "index": "pypi",
"version": "==4.1" "version": "==4.1.1"
}, },
"django-allow-cidr": { "django-allow-cidr": {
"hashes": [ "hashes": [
@ -196,11 +196,11 @@
}, },
"python-dotenv": { "python-dotenv": {
"hashes": [ "hashes": [
"sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f", "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5",
"sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938" "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"
], ],
"markers": "python_version >= '3.5'", "markers": "python_version >= '3.7'",
"version": "==0.20.0" "version": "==0.21.0"
}, },
"setuptools": { "setuptools": {
"hashes": [ "hashes": [
@ -225,6 +225,14 @@
], ],
"markers": "python_version >= '3.5'", "markers": "python_version >= '3.5'",
"version": "==0.4.2" "version": "==0.4.2"
},
"whitenoise": {
"hashes": [
"sha256:8e9c600a5c18bd17655ef668ad55b5edf6c24ce9bdca5bf607649ca4b1e8e2c2",
"sha256:8fa943c6d4cd9e27673b70c21a07b0aa120873901e099cd46cab40f7cc96d567"
],
"index": "pypi",
"version": "==6.2.0"
} }
}, },
"develop": { "develop": {
@ -291,11 +299,11 @@
}, },
"django": { "django": {
"hashes": [ "hashes": [
"sha256:031ccb717782f6af83a0063a1957686e87cb4581ea61b47b3e9addf60687989a", "sha256:a153ffd5143bf26a877bfae2f4ec736ebd8924a46600ca089ad96b54a1d4e28e",
"sha256:032f8a6fc7cf05ccd1214e4a2e21dfcd6a23b9d575c6573cacc8c67828dbe642" "sha256:acb21fac9275f9972d81c7caf5761a89ec3ea25fe74545dd26b8a48cb3a0203e"
], ],
"index": "pypi", "index": "pypi",
"version": "==4.1" "version": "==4.1.1"
}, },
"django-debug-toolbar": { "django-debug-toolbar": {
"hashes": [ "hashes": [

View file

@ -41,6 +41,15 @@ services:
- POSTGRES_USER=user - POSTGRES_USER=user
- POSTGRES_PASSWORD=feedabee - POSTGRES_PASSWORD=feedabee
node:
image: node
volumes:
- .:/app
working_dir: /app
stdin_open: true
tty: true
command: ./run_node_watch.sh
pa11y: pa11y:
build: build:
context: . context: .

35
src/gulpfile.js Normal file
View file

@ -0,0 +1,35 @@
/* gulpfile.js */
const uswds = require('@uswds/compile');
/**
* USWDS version
* Set the version of USWDS you're using (2 or 3)
*/
uswds.settings.version = 3;
/**
* Path settings
* Set as many as you need
*/
const ASSETS_DIR = './registrar/assets/';
uswds.paths.dist.css = ASSETS_DIR + 'css';
uswds.paths.dist.sass = ASSETS_DIR + 'sass';
uswds.paths.dist.theme = ASSETS_DIR + 'sass/_theme';
uswds.paths.dist.fonts = ASSETS_DIR + 'fonts';
uswds.paths.dist.js = ASSETS_DIR + 'js';
uswds.paths.dist.img = ASSETS_DIR + 'img';
/**
* Exports
* Add as many as you need
*/
exports.init = uswds.init;
exports.compile = uswds.compile;
exports.watch = uswds.watch;
exports.copyAssets = uswds.copyAssets

60
src/package-lock.json generated
View file

@ -1064,9 +1064,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001393", "version": "1.0.30001399",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001399.tgz",
"integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "integrity": "sha512-4vQ90tMKS+FkvuVWS5/QY1+d805ODxZiKFzsU8o/RsVJz49ZSRR8EjykLJbqhzdPgadbX6wB538wOzle3JniRA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -1690,9 +1690,9 @@
} }
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.244", "version": "1.4.248",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.244.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.248.tgz",
"integrity": "sha512-E21saXLt2eTDaTxgUtiJtBUqanF9A32wZasAwDZ8gvrqXoxrBrbwtDCx7c/PQTLp81wj4X0OLDeoGQg7eMo3+w==", "integrity": "sha512-qShjzEYpa57NnhbW2K+g+Fl+eNoDvQ7I+2MRwWnU6Z6F0HhXekzsECCLv+y2OJUsRodjqoSfwHkIX42VUFtUzg==",
"dev": true "dev": true
}, },
"node_modules/element-closest": { "node_modules/element-closest": {
@ -2030,9 +2030,9 @@
} }
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.2.11", "version": "3.2.12",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
"integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
@ -2405,9 +2405,9 @@
"dev": true "dev": true
}, },
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.1.2", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
@ -6597,9 +6597,9 @@
} }
}, },
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.0.7", "version": "1.0.9",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz",
"integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -7742,9 +7742,9 @@
"dev": true "dev": true
}, },
"caniuse-lite": { "caniuse-lite": {
"version": "1.0.30001393", "version": "1.0.30001399",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001399.tgz",
"integrity": "sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==", "integrity": "sha512-4vQ90tMKS+FkvuVWS5/QY1+d805ODxZiKFzsU8o/RsVJz49ZSRR8EjykLJbqhzdPgadbX6wB538wOzle3JniRA==",
"dev": true "dev": true
}, },
"check-types": { "check-types": {
@ -8237,9 +8237,9 @@
} }
}, },
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.4.244", "version": "1.4.248",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.244.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.248.tgz",
"integrity": "sha512-E21saXLt2eTDaTxgUtiJtBUqanF9A32wZasAwDZ8gvrqXoxrBrbwtDCx7c/PQTLp81wj4X0OLDeoGQg7eMo3+w==", "integrity": "sha512-qShjzEYpa57NnhbW2K+g+Fl+eNoDvQ7I+2MRwWnU6Z6F0HhXekzsECCLv+y2OJUsRodjqoSfwHkIX42VUFtUzg==",
"dev": true "dev": true
}, },
"element-closest": { "element-closest": {
@ -8514,9 +8514,9 @@
} }
}, },
"fast-glob": { "fast-glob": {
"version": "3.2.11", "version": "3.2.12",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
"integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
@ -8812,9 +8812,9 @@
"dev": true "dev": true
}, },
"get-intrinsic": { "get-intrinsic": {
"version": "1.1.2", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
"dev": true, "dev": true,
"requires": { "requires": {
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
@ -12042,9 +12042,9 @@
"dev": true "dev": true
}, },
"update-browserslist-db": { "update-browserslist-db": {
"version": "1.0.7", "version": "1.0.9",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz",
"integrity": "sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==", "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==",
"dev": true, "dev": true,
"requires": { "requires": {
"escalade": "^3.1.1", "escalade": "^3.1.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -0,0 +1,28 @@
/*
* * * * * ==============================
* * * * * ==============================
* * * * * ==============================
* * * * * ==============================
========================================
========================================
========================================
----------------------------------------
USWDS THEME CUSTOM STYLES
----------------------------------------
!! Copy this file to your project's
sass root. Don't edit the version
in node_modules.
----------------------------------------
Custom project SASS goes here.
i.e.
@include u-padding-right('05');
----------------------------------------
*/
@use "uswds-core" as *;
// Test custom style
p {
color: color('blue-10v');
}

View file

@ -0,0 +1,22 @@
/*
----------------------------------------
USWDS with settings overrides
----------------------------------------
Uncomment the following lines and add a list of changed settings
in the form $setting: value,
----------------------------------------
*/
//
// @use "uswds-core" with (
// $setting: value,
// $setting: value
// );
//
@use "uswds-core" with (
$theme-banner-background-color: "ink",
$theme-banner-link-color: "primary-light",
$theme-banner-max-width: "none",
$theme-show-notifications: false,
$theme-hero-image: "../img/registrar/dotgov_banner.png"
)

View file

@ -0,0 +1,11 @@
/*--------------------------------------------------
--- USWDS Settings --------------------------------*/
@forward "uswds-theme";
/*--------------------------------------------------
--- USWDS Source ----------------------------------*/
@forward "uswds";
/*--------------------------------------------------
--- Custom Styles ---------------------------------*/
@forward "uswds-theme-custom-styles";

View file

@ -88,6 +88,8 @@ INSTALLED_APPS = [
MIDDLEWARE = [ MIDDLEWARE = [
# django-allow-cidr: enable use of CIDR IP ranges in ALLOWED_HOSTS # django-allow-cidr: enable use of CIDR IP ranges in ALLOWED_HOSTS
"allow_cidr.middleware.AllowCIDRMiddleware", "allow_cidr.middleware.AllowCIDRMiddleware",
# serve static assets in production
"whitenoise.middleware.WhiteNoiseMiddleware",
# provide security enhancements to the request/response cycle # provide security enhancements to the request/response cycle
"django.middleware.security.SecurityMiddleware", "django.middleware.security.SecurityMiddleware",
# store and retrieve arbitrary data on a per-site-visitor basis # store and retrieve arbitrary data on a per-site-visitor basis
@ -130,7 +132,11 @@ WSGI_APPLICATION = "registrar.config.wsgi.application"
# will place static files for deployment. # will place static files for deployment.
# Do not use this directory for permanent storage - # Do not use this directory for permanent storage -
# it is for Django! # it is for Django!
STATIC_ROOT = BASE_DIR / "static" STATIC_ROOT = BASE_DIR / "public"
STATICFILES_DIRS = [
BASE_DIR / "assets",
]
# TODO: decide on template engine and document in ADR # TODO: decide on template engine and document in ADR
TEMPLATES = [ TEMPLATES = [
@ -388,6 +394,7 @@ SECURE_SSL_REDIRECT = True
# web server configurations. # web server configurations.
ALLOWED_HOSTS = [ ALLOWED_HOSTS = [
"getgov-unstable.app.cloud.gov", "getgov-unstable.app.cloud.gov",
"getgov-staging.app.cloud.gov",
"get.gov", "get.gov",
] ]

View file

@ -8,9 +8,13 @@ from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.urls import include, path from django.urls import include, path
from registrar.views import health from registrar.views import health, index
urlpatterns = [path("admin/", admin.site.urls), path("health/", health.health)] urlpatterns = [
path("admin/", admin.site.urls),
path("", index.index),
path("health/", health.health),
]
if settings.DEBUG: if settings.DEBUG:
import debug_toolbar import debug_toolbar

View file

@ -0,0 +1,215 @@
<!doctype html>{# keep this on the first line #}
{% load i18n static %}
<html class="no-js" lang="{{ LANGUAGE_CODE }}">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>
{% block title %}{% endblock %}
{{ site.name }}
{% block extra_title %}{% endblock %}
</title>
<meta name="description" content="{% block description %}{% endblock %}">
{% block viewport_meta %}
<meta name="viewport" content="width=device-width, initial-scale=1">
{% endblock %}
{% block extra_meta %}{% endblock extra_meta %}
{# TO-DO: Determine if <link rel="manifest" href="site.webmanifest"> is desirable #}
{# TO-DO: set defaults for these #}
<link rel="shortcut icon" href="{% static 'img/favicon.png' %}">
<link rel="apple-touch-icon" href="{% static 'img/touch-icon.png' %}">
{% block css %}
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
<script src="{% static 'js/uswds-init.min.js' %}" defer></script>
{% endblock %}
{% block canonical %}
<link rel="canonical" href="{{ current_path }}">
{% endblock %}
{% block feeds %}{% endblock %}
{% block extra_head %}{% endblock %}
{# hat tip to USWDS... #}
<!-- * * * * * ======================= -->
<!-- * * * * * ======================= -->
<!-- * * * * * ======================= -->
<!-- * * * * * ======================= -->
<!-- ================================= -->
<!-- ================================= -->
<!-- ================================= -->
</head>
<body id="{% block body_id %}default{% endblock %}" class="{% block body_class %}section_front{% endblock %}">
<script src="{% static 'js/uswds.min.js' %}" defer></script>
<a class="usa-skipnav" href="#main-content">Skip to main content</a>
<section class="usa-banner" aria-label="Official government website">
<div class="usa-accordion">
<header class="usa-banner__header">
<div class="usa-banner__inner">
<div class="grid-col-auto">
<img
class="usa-banner__header-flag"
src="{% static 'img/us_flag_small.png' %}"
alt="U.S. flag"
/>
</div>
<div class="grid-col-fill tablet:grid-col-auto">
<p class="usa-banner__header-text">
An official website of the United States government
</p>
<p class="usa-banner__header-action" aria-hidden="true">
Heres how you know
</p>
</div>
<button
class="usa-accordion__button usa-banner__button"
aria-expanded="false"
aria-controls="gov-banner-default-default"
>
<span class="usa-banner__button-text">Heres how you know</span>
</button>
</div>
</header>
<div
class="usa-banner__content usa-accordion__content"
id="gov-banner-default-default"
>
<div class="grid-row grid-gap-lg">
<div class="usa-banner__guidance tablet:grid-col-6">
<img
class="usa-banner__icon usa-media-block__img"
src="{% static 'img/icon-dot-gov.svg' %}"
role="img"
alt=""
aria-hidden="true"
/>
<div class="usa-media-block__body">
<p>
<strong>Official websites use .gov</strong><br />A
<strong>.gov</strong> website belongs to an official government
organization in the United States.
</p>
</div>
</div>
<div class="usa-banner__guidance tablet:grid-col-6">
<img
class="usa-banner__icon usa-media-block__img"
src="{% static 'img/icon-https.svg' %}"
role="img"
alt=""
aria-hidden="true"
/>
<div class="usa-media-block__body">
<p>
<strong>Secure .gov websites use HTTPS</strong><br />A
<strong>lock</strong> (
<span class="icon-lock"
><svg
xmlns="http://www.w3.org/2000/svg"
width="52"
height="64"
viewBox="0 0 52 64"
class="usa-banner__lock-image"
role="img"
aria-labelledby="banner-lock-title-default banner-lock-description-default"
focusable="false"
>
<title id="banner-lock-title-default">Lock</title>
<desc id="banner-lock-description-default">A locked padlock</desc>
<path
fill="#000000"
fill-rule="evenodd"
d="M26 0c10.493 0 19 8.507 19 19v9h3a4 4 0 0 1 4 4v28a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V32a4 4 0 0 1 4-4h3v-9C7 8.507 15.507 0 26 0zm0 8c-5.979 0-10.843 4.77-10.996 10.712L15 19v9h22v-9c0-6.075-4.925-11-11-11z"
/>
</svg> </span
>) or <strong>https://</strong> means youve safely connected to
the .gov website. Share sensitive information only on official,
secure websites.
</p>
</div>
</div>
</div>
</div>
</div>
</section>
{% block banner %}
<header class="usa-header usa-header-extended" role="banner">
<div class="usa-navbar">
{% block logo %}
<div class="usa-logo" id="extended-logo">
<em class="usa-logo-text">
<a href="/"
title="Home"
aria-label="Home">
{% block site_name %}{{ site.name }}{% endblock %}
</a>
</em>
</div>
{% endblock %}
<button class="usa-menu-btn">Menu</button>
</div>
{% block usa_nav %}
{% block usa_nav_secondary %}{% endblock %}
{% endblock %}
</header>
{% endblock banner %}
{% block usa_overlay %}<div class="usa-overlay"></div>{% endblock %}
<div id="wrapper">
{% block messages %}
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
{% endblock %}
{% block section_nav %}{% endblock %}
<main id="main-content">
{% block hero %}{% endblock %}
{% block content %}{% endblock %}
</main>
<div role="complementary">{% block complementary %}{% endblock %}</div>
{% block content_bottom %}{% endblock %}
</div>
<footer id="footer" role="contentinfo">
{% block footer_nav %}
{% endblock %}
{% block footer %}
<div>
<p class="copyright">&copy; {{ now.year }} {{ site.name }}</p>
</div>
{% endblock %}
</footer>
</div> <!-- /#wrapper -->
{% block init_js %}{% endblock %}{# useful for vars and other initializations #}
{% block site_js %}
{% endblock %}
{% block app_js %}{% endblock %}
{% block extrascript %}{% endblock %}
{# asynchronous analytics #}
<script async id="_fed_an_ua_tag" src="https://dap.digitalgov.gov/Universal­Federated­Analytics­M
in.js?agency={{ AGENCY }}"></script>
</body>
</html>

View file

@ -0,0 +1,18 @@
<!-- Test page -->
{% extends 'base.html' %}
{% block title %} Hello {% endblock %}
{% block hero %}
<section class="usa-hero">
<div class="usa-grid">
<div class="usa-hero-callout usa-section-dark">
<h2>
<span class="usa-hero-callout-alt">This is sample content.</span>
This is only sample content.
</h2>
<p> {{ name }} You'll want to replace it with content of your own.</p>
<button class="usa-button usa-button--accent-cool">Click a usa button</button>
</div>
</div>
</section>
{% endblock %}

View file

@ -0,0 +1,6 @@
from django.shortcuts import render
def index(request):
context = {"name": "World!"}
return render(request, "whoami.html", context)

19
src/run.sh Executable file
View file

@ -0,0 +1,19 @@
#/bin/bash
set -o errexit
set -o pipefail
# Only run migrations on the zeroth index when in a cloud.gov environment
if [[ -v CF_INSTANCE_INDEX && $CF_INSTANCE_INDEX == 0 ]]
then
python manage.py migrate --settings=registrar.config.settings --noinput
else
echo "Migrations did not run."
if [[ -v CF_INSTANCE_INDEX ]]
then
echo "CF Instance Index is ${CF_INSTANCE_INDEX}."
fi
fi
python manage.py collectstatic --settings=registrar.config.settings --noinput
gunicorn registrar.config.wsgi -t 60

15
src/run_node_watch.sh Executable file
View file

@ -0,0 +1,15 @@
#!/bin/bash
npm install
npm rebuild
dir=./registrar/assets
if [ -d "$dir" ]
then
echo "Compiling USWDS assets"
npx gulp copyAssets
npx gulp compile
else
echo "Initial USWDS assets build"
npx gulp init
npx gulp compile
fi
npx gulp watch