This is a web application to demonstrate the build, deployment and release workflow for applications in Distr. It consists of a next.js application, a Python backend and a Postgresql database. The containers are deployed via docker compose behind a Caddy reverse proxy, allowing access to the frontend and the Python API.
Feel free to fork it, tinker around a bit and find out what Distr can offer for your on premises software.
We make use of:
- GitHub Actions/Workflows
- GitHub Registry (
ghcr.io
) - Release Please
distr-create-version-action
Apart from a directory for the code, config and Dockerfile
of each the applications' components (backend
, frontend
, proxy
),
there are the following deployment specific files/directories:
.github/workflows/*.yaml
: These specify the GitHub action workflows.deploy/
: Contains the production docker compose file and an environment template. These will be uploaded to distr using thedistr-create-version-action
, as defined in the push-distr workflow.release-please-config.json
: Contains the config for the release please action.
The GitHub workflows behave differently in different scenarios. For example, when opening a PR after or during feature development, we want the docker build to run, but of course the built image should not be published or released yet.
When opening a PR, the build-*
jobs are run, i.e. each part of the application is built with docker. The corresponding
Dockerfile
s can be found inside each components' directory.
When pushing to main
, e.g. by merging a PR, the docker images are built again.
Additionally, the release-please
workflow is run. For that to work, the corresponding GitHub action needs permissions on the repository.
We set a GitHub secret in this repository and give it the name RELEASE_GITHUB_TOKEN
.
For more information about the Release Please token, please check their docs.
Once there is at least one commit to main
since the last release, Release Please will open a new PR or update its existing one.
The changeset will mostly include version changes and adding relevant information to the CHANGELOG
.
After testing and making sure everything is ready to release, you can approve and merge the Release Please PR. This will push a tag with the new version name to the repository. However you can also push a tag by yourself – it will also start the defined workflows.
The build-*
workflows are started again, however this time, as the triggering event is a tag push, they will also log in to
the GitHub registry before the build, and afterwards push the resulting images to the registry.
On release, additionally, the push-distr
workflow is started,
which uploads the artifacts in deploy/
(docker-compose.yaml
and env.template
)to the Distr Hub,
and makes the new version available to you and your customers. The used version name is the pushed git Tag.
This GitHub action needs to authenticate itself against the Distr Hub, and it needs additional information as to which application the new version should be added to. Therefore follow these one-time setup steps:
- Create a Distr Personal Access Token in your account, as described here.
- Add the Distr PAT to your GitHub repo's secrets and call it
DISTR_TOKEN
. - Make sure to have a Distr application in place, to which the newly released version can be attached. If the application does not exist yet,
create it via the Distr Web interface, by giving it a name (like
hello-distr
) and setting the type todocker
. Once created, copy the ID of the application from the web interface (click on the left-most column in the application list). - Add the copied application ID as a variable to your GitHub repository and call it
DISTR_APPLICATION_ID
. Alternatively you can also directly paste it into thepush-distr.yaml
workflow file (but please never directly paste any tokens/secrets!).
See distr-create-version-action docs for further information regarding this GitHub action.
Note that in this example repo, we set the api-base
to https://demo.distr.sh/api/v1
. In order to make use of this in production,
you should remove this line to use the default Distr Hub (app.distr.sh
) instead.
We often want to display the software's own version in the user interface.
To that end we can pass the version name (i.e. the git tag) to the environment of the frontend docker build, which itself
writes this version into a version.json
file inside the app. The version defined in this file will then be displayed in a
frontend component.
To add the argument to the docker build (see .github/workflows/build-frontend.yaml
):
build-args: |
VERSION=${{ github.ref_name }}
To accept this VERSION
environment variable (see frontend/Dockerfile
):
ARG VERSION
ENV VERSION=${VERSION}
To write the version file inside the frontend repo, there is the frontend/hack/update-frontend-version.js
script:
const out = JSON.stringify({version: env['VERSION'] || 'snapshot'}, null, 2)
await writeFile('buildconfig/version.json', out);
This script is hooked into the next.js build process as prebuild
, see frontend/package.json
:
"prebuild": "npm run buildconfig",
"buildconfig": "node hack/update-frontend-version.js"
So far we have managed to build and release a new version of hello-distr
and to publish the deploy artifacts to Distr Hub.
Let's now take a look at these artifacts.
You can find the production compose file at deploy/docker-compose.yaml
. For all the services to start up and run correctly,
some environment variables need to be passed from the outside. You or your customer (depending on the deployment environment)
will have to set these variables, when deploying the hello-distr
application via the Distr web interface.
In order to make this process easier for you and your customers, you can define an optional environment template
(see deploy/env.template
) and upload it to Distr with the template-file
parameter of the GitHub action.
This template is a simple text file with KEY=VALUE
lines. Note: This template is only for the user to set the possible environment
values when deploying the app via Distr – and it will only be shown at the first deployment of this app. When later updating
to a newer version, the deploy modal in the Distr web interface will show the previously set variables, not the template!
You can use this template to set recommended values and to leave additional comments.
Once deployed, the hello-distr
app will be available at port 80 of the given hostname (env variable HELLO_DISTR_HOST
).
The user interface will be available at http://<hostname>
, and the python API will be available at http://<hostname>/api
.
The UI consists of only one page showing the deployed version and the latest entry in the messages
table of the postgres DB.
To demonstrate that the API is also publicly available, you can POST
a newer message to it:
curl -X POST http://<your-hostname>/api/messages -d '{"text": "hello distr lol"}' -H 'Content-Type: application/json'
After refreshing the UI, it should display the newly added message.
Postgres
You can install Postgres locally or use Docker to run it in a container.
docker compose up
To start the backend or frontend, please consult the respective README
s in the subdirectories.