Zuul Dashboard Javascript
zuul-web has an html, css and javascript component, zuul-dashboard, that is managed using Javascript toolchains. It is intended to be served by zuul-web directly from zuul/web/static in the simple case, or to be published to an alternate static web location, such as an Apache server.
The web dashboard is written in React and PatternFly and is managed by create-react-app and yarn which in turn both assume a functioning and recent nodejs installation.
Note
The web dashboard source code and package.json are located in the web
directory. All the yarn commands need to be executed from the web
directory.
For the impatient who don’t want deal with javascript toolchains
tl;dr - You have to build stuff with javascript tools.
The best thing would be to get familiar with the tools, there are a lot of good features available. If you’re going to hack on the Javascript, you should get to know them.
If you don’t want to hack on Javascript and just want to run Zuul’s tests,
tox
has been set up to handle it for you.
If you do not have yarn installed, tox
will use nodeenv to install
node into the active python virtualenv, and then will install yarn into
that virtualenv as well.
yarn dependency management
yarn manages the javascript dependencies. That means the first step is getting yarn installed.
tools/install-js-tools.sh
The tools/install-js-tools.sh
script will add apt or yum repositories and
install nodejs and yarn from them. For RPM-based distros it needs to know
which repo description file to download, so it calls out to
tools/install-js-repos-rpm.sh
.
Once yarn is installed, getting dependencies installed is:
yarn install
The yarn.lock
file contains all of the specific versions that were
installed before. Since this is an application it has been added to the repo.
To add new runtime dependencies:
yarn add awesome-package
To add new build-time dependencies:
yarn add -D awesome-package
To remove dependencies:
yarn remove terrible-package
Adding or removing packages will add the logical dependency to package.json
and will record the version of the package and any of its dependencies that
were installed into yarn.lock
so that other users can simply run
yarn install
and get the same environment.
To update a dependency:
yarn add awesome-package
Dependencies are installed into the node_modules
directory. Deleting that
directory and re-running yarn install
should always be safe.
Dealing with yarn.lock merge conflicts
Since yarn.lock
is generated, it can create merge conflicts. Resolving
them at the yarn.lock
level is too hard, but yarn itself is
deterministic. The best procedure for dealing with yarn.lock
merge
conflicts is to first resolve the conflicts, if any, in package.json
. Then:
yarn install --force
git add yarn.lock
Which causes yarn to discard the yarn.lock
file, recalculate the
dependencies and write new content.
React Components and Styling
Each page is a React Component. For instance the status.html page code
is web/src/pages/status.jsx
. It is usually a good idea not to put
too much markup in those page components and create different
components for this instead. This way, the page component can deal
with the logic like reloading data if needed or evaluating URL
parameters and the child components can deal with the markup. Thus,
you will find a lot of components in the web/src/containers
directory that mainly deal with the markup.
Mapping of pages/urls to components can be found in the route list in
web/src/routes.js
.
The best way to get started is to check out the libraries that glue everything together. Those are React, react-router and Redux.
For the visual part we are using PatternFly. For a list of available PatternFly React components, take a look at the Components section in their documentation. If a single component is not enough, you could also take a look at the Demos sections which provides some more advanced examples incorporating multiple components and their interaction.
If you are unsure which component you should use for your purpose, you might want to check out the Usage and behaviour section in their design guidelines.
There is also a list of available icons including some recommendations on
when to use which icon. In case you don’t find an appropriate icon there, you
could check out the FontAwesome Free icons, as most of them are included in
PatternFly. To find out if an icon is available, simply try to import it from
the @patternfly/react-icons
package.
For example if you want to use the address-book icon (which is not listed in the PatternFly icon list) you can import it via the following statement:
import { AddressBookIcon } from '@patternfly/react-icons'
Please note that the spelling of the icon name changes to CamelCase and is
always extended by Icon
.
Development
Building the code can be done with:
yarn build
zuul-web has a static
route defined which serves files from
zuul/web/static
. yarn build
will put the build output files
into the zuul/web/static
directory so that zuul-web can serve them.
Development server that handles things like reloading and hot-updating of code can be started with:
yarn start
will build the code and launch the dev server on localhost:3000. Fake
api response needs to be set in the web/public/api
directory.
mkdir public/api/
for route in info status jobs builds; do
curl -o public/api/${route} https://zuul.openstack.org/api/${route}
done
To use an existing zuul api, uses the REACT_APP_ZUUL_API environment variable:
# Use openstack zuul's api:
yarn start:openstack
# Use software-factory multi-tenant zuul's api:
yarn start:multi
# Use a custom zuul:
REACT_APP_ZUUL_API="https://zuul.example.com/api/" yarn start
To run eslint tests locally:
yarn lint
Authentication
The docker-compose file in doc/source/examples/keycloak
can be
used to run a Keycloak server for use with a development build of the
web app. The default values in that file are already set up for the
web app running on localhost. See the Keycloak tutorial for details.
Deploying
The web application is a set of static files and is designed to be served
by zuul-web from its static
route. In order to make sure this works
properly, the javascript build needs to be performed so that the javascript
files are in the zuul/web/static
directory. Because the javascript
build outputs into the zuul/web/static
directory, as long as
yarn build
has been done before pip install .
or
python setup.py sdist
, all the files will be where they need to be.
As long as yarn is installed, the installation of zuul will run
yarn build
appropriately.
By default, zuul-web provides a Progressive Web Application but does
not run a Service Worker. For deployers who would like to enable one,
set the environment variable
REACT_APP_ENABLE_SERVICE_WORKER=true
during installation.