The ubuntu.com codebase is a Flask app, which builds on our own flask-base, templatefinder, blog and search packages.
We use Yarn for building static files like CSS through package.json scripts.
The recommended way to run the site is with the dotrun snap:
sudo snap install dotrun
dotrun # Build dependencies and run the serverThen to learn about dotrun's options, type:
dotrun --helpSince the site is basically a Flask app, you can also run the site in the traditional way using python 3 and venv:
python3 -m venv env
source env/bin/activate
pip install -r requirements.txt
./entrypoint 127.0.0.0:8001Now browse to the site at http://127.0.0.1:8001. If it looks a bit odd, it's probably because you haven't built sass - see below.
You can run deactivate to shutdown the virtual environment when you are done.
The CSS needs to be built from the static/css/styles.scss file. This in turn requires vanilla-framework.
If you can't build using the ./run build command, you can pull down dependencies this using yarn:
yarn installThen you can use the built in scripts to build or watch the Sass:
yarn run build # Build the Sass to CSS then exit
yarn run watch # Dynamically watch for Sass changes and build CSSYou can use the ./run script to use Node modules from a local folder on a one-time basis, instead of the modules declared in package.json, as follows:
./run --node-module $HOME/projects/vanilla-framework watch # Build CSS dynamically, using a local version of vanilla-frameworkGuides for making changes to the ubuntu.com codebase.
The basic navigation structure of the site is listed in navigation.yaml. This file lists all the top-level section pages and their children and grandchildren. The top menu, footer menu and breadcrumb navigation are all built from this list.
An example of the file structure can be found at the top of the file.
If a child is "hidden", then it won't be displayed in the navigation menus, either in the top nav, the footer nav, or in the breadcrumb nav on other pages.
The navigation.yaml file is read in webapp/context.py. A function get_navigation is created and then made available to all Jinja templates.
For each dropdown window we use a separate file which individually calls the get_navigation script, passing the specific section of the navigation it wants to build. This allows us to load each dropdown, seen here, as needed and saves on initial load times.
The navigation is supported by navigation.js for its functionality. In the case where JS is not available we make a static version under the /navigation-nojs endpoint.
On mobile we have a pattern of showing the section title next to the logo, e.g.
For the most part this will happen automatically as long as the subpages (/appliance/community) are in navigtation.yml as children. In some cases this isn't possible due to dynamically created content such as tutorials. In this case you can set the section_title and section_path variables in the template e.g.
{% set section_title="Tutorials" %}
{% set section_path="/tutorials" %}
{% block content %}
{% endblock %}
Some tests use VCR.py to record and replay HTTP interactions (cassettes). When APIs change or new tests are added, you may need to re-record the cassettes.
To update cassettes, run the tests with the VCR_RECORD_MODE environment variable set to all:
# Record new cassettes
dotrun -e VCR_RECORD_MODE=all test-pythonAlternatively, add VCR_RECORD_MODE=all to your .env.local file temporarily while re-recording.
After recording, verify the tests pass without the environment variable (using the recorded cassettes):
dotrun test-pythonNote: Cassettes are stored in tests/cassettes/. Review the changes before committing to ensure no sensitive data was recorded.
If you want to work on Credentials you need to add some environment vars into your .env.local.
If you have a TrueAbility account with API access enabled, you can find your API key in Settings.
TRUEABILITY_URL="https://app3.trueability.com"
TRUEABILITY_API_KEY=<trueability_api_key>
BADGR_URL=https://api.test.badgr.com
BAGDR_USER=<badgr_user>
BADGR_PASSWORD=<badgr_password>
Parts of this site use React Query to manage data from the API.
To enable the React Query devtools you need to add NODE_ENV="development" to your .env.local file or run: dotrun -e NODE_ENV="development".
When making changes to the codebase please make sure it's properly formatted and linted. Our standards suggest that our editors should be configured in the following ways:
- Python files should be formatted with
blackon save, and checked withflake8 - JS files should be formatted with
prettierand checked witheslint - CSS files should be formatted with
prettierand checked withstylelint - Jinja templates should be formatted and checked with
djLint
These tools should take their configuration from files stored in our codebases, e.g. .eslintrc.js. Additionally, editor settings (indentation etc.) for particular types of files should be picked up from .editorconfig files if they exist in the codebase.
First install the necessary tools globally:
sudo apt update && sudo apt install python3-pip nodejs
# (for macOS hopefully these can be installed with brew instead?)
sudo pip3 install black flake8
sudo npm install -g prettier eslint stylelint
python -m pip install -U djlintThese are instructions for setting up various editors to use the above tools:
VSCode Install the following extensions:
Then tweak some settings by opening your JSON settings (CTRL+Shift+P, type "Settings", click "Open settings (JSON)"), and adding the following rules:
{
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black",
"python.formatting.blackArgs": [
"--line-length",
"79"
],
"editor.formatOnSave": true,
"[html][jinja-html][jinja]": {
"editor.formatOnSave": false,
"editor.defaultFormatter": "monosans.djlint"
},
"html.format.wrapLineLength": 0,
"html.format.wrapAttributes": "aligned-multiple",
"html.format.indentHandlebars": true,
"html.format.preserveNewLines": false,
}Atom Install the following plugins:
- linter (needed for all linting)
- linter-flake8
- linter-eslint
- linter-sass-lint
- linter-stylelint
- python-black
- prettier-atom
Configure the python-black plugin to add the --line-length 79 option.
Sublime Install the following plugins:
PyCharm Make sure you have the File Watcher plugin installed.
Configure Black
Go to Preferences or Settings -> Tools -> File Watchers and click + to add a new watcher:
- Name: Black
- File type: Python
- Scope: Project Files
- Program: run
which blackto find out - Arguments:
--line-length 79 $FilePath$ - Output paths to refresh:
$FilePath$ - Working directory:
$ProjectFileDir$
Source: https://black.readthedocs.io/en/stable/editor_integration.html
Configure Flake8
Go to Preferences or Settings -> Tools -> File Watchers and click + to add a new watcher:
- Name: Flake8
- File type: Python
- Scope: Project Files
- Program: run
which flake8to find out - Arguments:
$FilePath$ - Output paths to refresh:
$FilePath$ - Working directory:
$ProjectFileDir$
