...
This application is based on the Wagtail CMS. It utilises:
- Wagtail CMS
- Python/Django framework
- jQuery
- SASS
The following command will need to be run to make the codebase work in LIVE:
$ cp docker-compose.yml.example docker-compose.yml
Variable | Default | Description |
---|---|---|
DBHOST | host.docker.internal | DB host url/string |
DBPORT | 5432 | DB connection port |
DBNAME | discoveruni | DB name to use |
DBUSER | DB user | |
DBPASSWORD | DB password | |
SEARCHAPIHOST | The url endpoint for the search api | |
DATASETAPIHOST | The url endpoint for the dataset api | |
WIDGETAPIKEY | The access key for the api for the widget | |
DATASETAPIKEY | The access key for the api for the site | |
FEEDBACK_API_HOST | The url endpoint for the feedback api | |
AZURE_ACCOUNT_NAME | The name of the account for image storage | |
AZURE_ACCOUNT_KEY | The access key to account for image storage | |
AZURE_ACCOUNT | The account for image storage | |
JSONFILES_STORAGE_CONTAINER | The container URI for the json files | |
SENDGRID_API_KEY | The API key for the e-mail notifications | |
SENDGRID_FROM_EMAIL | The e-mail address used for notifications | |
SORT_BY_SUBJECT_LIMIT | 5000 | Used to determine how to display subjects |
LOCAL | False | Tells the site to use external API or mocks |
SITEMAP_STORAGE_BLOB | Tells the app where the dynamic sitemap is stored | |
The docker image for this branch is created differently from the other branches (python manage.py runserver 0.0.0.0
is now run inside the image, not as a command on the image in the docker-compose.yml
). This means that the old containers and images for other branches need to be deleted so the new one can be built.
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
<container_id> wagtail-cms_web "python manage.py ru…" 3 days ago Exited (0) 3 days ago wagtail-cms_web_1
............ ..... "...................." .......... ............. 27017/tcp .................
$ docker rmi -f <container_id>
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wagtail-cms_web latest <image_id> 11 days ago 1.07GB
............... latest ............ 3 weeks ago ......
$ docker rm <image_id>
...
This now means when you run docker-compose up
docker will rebuild the image using the new commands in the Dockerfile
, and then build a new container from that
REMEMBER: To run the commands above when switching back to the other branches on the project
$ docker container exec -it wagtail-cms_web_1 python manage.py test
IMPORTANT: When fixing an issue write a test first to prove it's broken. Then, and only then, fix the problem
$ python3
>>> import secrets
>>> chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
>>> ''.join(secrets.choice(chars) for i in range(50))
<secret_key>
>>> exit()
$ vim docker-compose.yml
...
SECRET_KEY: "<secret_key>"
...
$ cp docker-compose.yml.example docker-compose.yml
$ vim docker-compose.yml
...
DBHOST: "db"
DBNAME: "django"
DBUSER: "docker"
DBPASSWORD: "docker"
...
...
MONGODB_HOST: "mongo"
MONGODB_USERNAME: "mongodb"
MONGODB_PASSWORD: "mongodb"
...
SEARCHAPIHOST: "..."
...
$ docker-compose up
If docker fails to start up because the
SECRET_KEY
, re-create the secret key and try again. Sometime it fails because of the use of irregular or un-escapped characters.
If this is the first time working on the code base remember to populate PostgreSQL and MongoDB
If you are going to be importing new data to the fixtures remember to set DATASETAPIHOST, DATASETAPIKEY, AZURECOSMOSDBURI and AZURECOSMOSDBKEY
You need to have Docker installed to be able to see changes in the code, run tests and update local data.
$ docker-compose up
Make sure to run this command in a separate window so you have somewhere to run other commands from
This command will download all the required images (Python, PostgreSQL, CosmosDB) and start them for you all preconfigured
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_cms
This will run the command content/management/commands/populate_cms.py
. This command loads the data found at CMS/fixtures/postgres.json
into the database.
You might ask why you can't use Django and to run ... python manage.py loaddata CMS/fixtures/postgres.json
. The foreign key constraints in Wagtail prevent this. When trying to run loaddata
Django will fail in deleting (truncating) the old data. The populate_cms
command gets round this by calling a custom flush command (content/management/commands/flush_db.py
) that exposes the --allow-cascade
flag on Django's own flush command. In additional it deletes a number of default posts and content types that are created when migrations are run and prevent the postgres.json
file from being inserted into the database.
$ docker container exec -it wagtail-cms_web_1 python manage.py update_cms_fixture --db_host ... --db_name ... --db_user ... --db_password ... --db_port ...
Use the creds for the remote PostgreSQL in the above statement
Want to make sure the command above is not in your command history for people to find on your machine? Then do the following.
$ set +o history
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_cms ...
$ set -o history
Already in your command history but want to delete it?
$ history | tail -n 5
100 ...
101 ...
102 ... # <- You want to delete this one
103 ...
104 ...
$ history -d 103
Stop docker before running the following command
You can stop docker by pressing
Ctrl+C
in the window in which it is running.
$ sudo rm -rf data/postgres
$ docker-compose up
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_institutions
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_courses
populate_courses
will get the courses insettings.TEST_COURSES
from CosmosDB and put them in MongoDB (as well as populate the file found incourses/fixtures/courses.json
)
If the course data has changed remotely and you want to update it locally then do the following:
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_courses --update
...
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_courses
...
The first command goes to the CosmosDB (as defined by
AZURECOSMOSDBURI
indocker-compose.yml
) and copies the courses specified inTEST_COURSES
indocker-comnpose.yml
to tocourses/fixtures/courses.json
. The second command gets the contents ofcourses/fixtures/courses.json
and puts them in the local MongoDB instance.
Don't forget to commit the changes to the course data to the repo
$ git add courses/fixtures/courses.json
$ git commit -m '...'
$ vim docker-compose.yml
...
TEST_COURSES = 'U18-LAWLLB,AB35,...'
...
$ vim docker-compose.yml.example
...
TEST_COURSES = 'U18-LAWLLB,AB35,...'
...
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_courses --update
...
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_courses
...
$ git add docker-compose.yml.example
$ git add courses/fixtures/courses.json
$ git commit -m '...'
...
If the course data has changed remotely and you want to update it locally then do the following:
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_institutions --update
...
$ docker container exec -it wagtail-cms_web_1 python manage.py populate_institutions
...
Don't forget to commit the changes to the institutions data to the repo
$ git add institutions/fixtures/institutions.json
$ git commit -m '...'
Stop docker before running the following command
You can stop docker by pressing
Ctrl+C
in the window in which it is running.
$ sudo rm -rf data/mongodb
$ docker-compose up
The following URLs work in development
$ wget http://localhost:8000/institution-details/<any_institution>/
$ wget http://localhost:8000/admin/ # <- All wagtail pages
$ wget http://localhost:8000/course-details/10007804/U18-LAWLLB/Full-time/
$ wget http://localhost:8000/course-details/10000055/AB35/Full-time/
$ wget http://localhost:8000/course-details/10001850/PBSFND-D_FT/Full-time/
$ wget http://localhost:8000/course-details/10007165/U09FUECW/Full-time/
$ wget http://localhost:8000/course-details/10007767/UMDAHFY/Full-time/
$ docker images
From this list you can find the docker images you no longer need. Copy their IMAGE ID
$ docker rm <IMAGE_ID>
Container are based of images. This is what runs your code
$ docker ps --all
The NAME
s you can see in the commands above. The STATUS
tells you whether ac container is being used. If you no longer need a container copy the CONTAINER ID
$ docker rmi -f <CONTAINER_ID>
$ docker container exec -it wagtail-cms_web_1 bash
$ docker container exec -it wagtail-cms_db_1 bash
$ docker container exec -it wagtail-cms_web_1 python manage.py shell
$ docker container exec -it wagtail-cms_web_1 pip install ...
$ docker container exec -it wagtail-cms_web_1 pip freeze > requirements.txt
If you add environment variable to docker-compose.yml
don't forget to also add it to CMS/settings/base.py
The continuous integration and deployment pipeline for this project is implemented using Azure DevOps pipelines.
The continuous integration pipeline for the project is defined in yml files in the root of the project, all starting with 'azure-pipelines'.
There are 4 pipelines defined in the project.
Defined in 'azure-pipelines.yml'
This pipeline should run on every push to Github from feature, bug and refactor branches. All this pipeline does is run the tests to regression check the new code.
Defined in 'dev-azure-pipelines.yml'
This pipeline should run on every push to Github on the develop branch. This pipeline runs the tests and, if they pass, builds a docker container and pushes it to the dev container registry.
Defined in 'pre-prod-azure-pipelines.yml'
This pipeline should run on every push to Github from a release branch. This pipeline runs the tests and, if they pass, builds a docker container and pushes it to the pre-prod container registry.
Defined in 'prod-azure-pipelines.yml'
This pipeline should run on every push to Github on the master branch. This pipeline runs the tests and, if they pass, builds a docker container and pushes it to the prod container registry.
The continuous deployment pipeline is defined through the Azure DevOps pipeline UI.
There are 3 pipelines setup for the project.
The pipeline runs when the Development CI pipeline passes, it pulls the container generated by the CI build on to the WebApp server and starts the container.
The pipeline runs when the a new container is pushed to the pre-prod container registry, it pulls the container on to the WebApp server and starts the container.
The pipeline runs when the a new container is pushed to the prod container registry, it pulls the container on to the WebApp server and starts the container.
Releases of the code are following the major/minor/patch pattern for release numbering.
New releases can be generated manually or by using the 'release' command in the bin directory.
- update the version number with in the version.txt file
- create a new branch named in the pattern 'release/v
version number
' (e.g. release/v0.0.1) - push the branch to Github
- ensure there are no uncommitted changes in your local repository
- call the 'release' command in the bin directory, passing as a parameter either major/minor/patch.
Once a release has been signed off and deployed to production, you need to:
- merge the release branch into master and to development.
- tag master with the release number at the point it was merged in.
- delete the release branch
See CONTRIBUTING for details.
See LICENSE for details.