### Nightly releases and Continous Integration for DUNE DAQ Software
DUNE DAQ/SC Meeting
Pengfei Ding
Fermilab
April 26, 2021
---
<style>
.reveal {
font-size: 24px;
}
.blue {
color: blue;
}
.green {
color: green;
}
.red {
color: red;
}
</style>
## Introduction (I)
* Continuous Integration (CI) practices:
* <span class="green">**commit often**</span> -- developers integrate code into share repository frequently (multiple times a day);
* <span class="green">**automatically built/tested**</span> each integration will be verified by automated build and tests;
* <span class="blue">Goal and benifits of CI</span>:
* ensure the most up-to-date (and tested) code is reflected and maintained;
* prevent backups and delays when multiple devs are ongoing.
* Continuous deployment (CD):
* Ongoing delivery of features as they are updated, tested and ready for release.
---
<img src="https://i.imgur.com/EuNf5BE.png" alt="CI drawing" style="width:600px;"/>
---
## Introduction to CI and nightly releases (II)
* Nightly releases:
* A step close to CD;
* the develop release is built/tested/deployed nightly;
* it will be the base for each repo's CI in the next day;
* <span class="red">**underlying requirement:**</span> releated PRs in multiple repos should be merged to develop on the same day.
* <span class="green">**Benifits:**</span>
* For developers -- ensuring their code can be successfully integrated into the release on a daily basis;
* For release managers -- ensuring the release is in good-standing and ready to be freezed and released.
* <span class="blue">Overall: Faster iterations, accelerated delivery, increased visibility of bugs and issues, low-risk releases.</span>
---
### Nightly releases (I)
* **Building:**
- Contains the <span class="blue">**HEAD of develop branch**</span> across all DAQ repositories;
- <span class="green">built on GitHub cloud node at 2:00am (CDT);</span>
- <span class="blue">build log and pre-built release (if the build succeeds) is saved for 90 days on GitHub;</span>
* **Deployment:**
- the release name is in the form of <span class="red">`NYY-MM-DD`</span>;
- the release will be deployed to `/cvmfs/dunedaq-development.opensciencegrid.org`;
- a soft link named `last_successful` will ponit to the most recent successfully built nightly release.
* **Usage:**
- <span class="green">Just as a typical frozen release,</span>
- use `-r` with the patth to the `nightly` directory in cvmfs
```sh
dbt-create.sh –r /cvmfs/dunedaq-development.opensciencegrid.org/nightly <NYY-MM-DD> workdir
```
---
### Nightly releases (II)
More details about how nightly releases are made:
* <span class="blue"> Release Definition: </span>
* the same way as we defined, e.g. `dunedaq-v2.4.0`;
* in the release manifest file `daq-release/configs/dunedaq-develop/release_manifest.sh`
* list of external packages and their versions;
* list of DAQ packages for the release.
* <span class="green">Building a docker image: </span>
- built by a daily cronjob running on a server with cvmfs access;
- based on `dunedaq/sl7-minimal:latest` image;
- adding a layer of disk mirror containing external packages from cvmfs;
- adding a layer of pre-built develop release;
- the image is tagged as `dunedaq/sl7-minimal:dev` (**reused tag**);
- and a **unique tag** `dunedaq/sl7-minimal-nightly:NYY-MM-DD`.
---
### Docker images
- <span class="blue"> GitHub Repo: </span> [daq-docker](https://github.com/DUNE-DAQ/daq-docker)
- `sl7-minimal` contains the `Dockerfile` for making `dunedaq/sl7-minimal:latest` image;
- any updates to the repo will <span class="red">trigger dockerhub to rebuild</span> this image;
- `sl7-ci` contains the `Dockerfile` and scripts to make the `dunedaq/sl7-minimal:dev` image;
- it is refreshed nightly by a cronjob on a Fermilab server with access to cvmfs.
- Dockerhub image: [dunedaq/sl7-minimal](https://hub.docker.com/repository/docker/dunedaq/sl7-minimal)
- Dockerhub image: [dunedaq/sl7-minimal-nightly](https://hub.docker.com/repository/docker/dunedaq/sl7-minimal-nightly)
---
### Nightly releases (III)
- <span class="blue"> Artifact generation: </span>
- a GitHub Action workflow in the `daq-release` repo;
- run one hour after the docker image was built
- checks out the develop branch of `daq-release` and `daq-buildtools`;
- sets up a working directory with only external packages from `dunedaq-develop` release;
- checks out develop branches of all DAQ packages and build the release;
- uploads the pre-built release as ”artifacts” of the CI job.
---
### Demo (I): nightly GitHub Action for `daq-release`
- Workflow status page: [Nightly workflow](https://github.com/DUNE-DAQ/daq-release/actions)
- [Latest workflow run](https://github.com/DUNE-DAQ/daq-release/actions/runs/762687473)
<img src="https://i.imgur.com/gSITupq.png" alt="CI drawing" style="width:600px;"/>
---
### Demo (II): nightly GitHub Action for `daq-release`
- [Workflow configuration file](https://github.com/DUNE-DAQ/daq-release/blob/develop/.github/workflows/nightly.yml)
```yaml=
# This is a basic workflow that is manually triggered
name: Nightly workflow
# Controls when the action will run. Workflow runs when manually triggered using the UI
# or API.
on:
#push:
#branches: [ develop ]
schedule:
- cron: "0 7 * * *"
workflow_dispatch:
# Inputs the workflow accepts.
inputs:
name:
# Friendly description to be shown in the UI instead of 'name'
description: 'Manual start the CI workflow'
# Default value if no value is explicitly provided
default: 'Yes'
# Input has to be provided for the workflow to run
required: true
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "greet"
bulid_the_develop_release:
# The type of runner that the job will run on
runs-on: ubuntu-latest
container:
image: dunedaq/sl7-minimal:dev
env:
DBT_AREA_FILE: "dbt-settings"
defaults:
run:
shell: bash
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Runs a single command using the runners shell
- name: Start the CI
run: echo "Start the CI anyway ${{ github.event.inputs.name }}"
- name: Checkout daq-buildtools
uses: actions/checkout@v2
with:
repository: DUNE-DAQ/daq-buildtools
path: daq-buildtools
- name: Checkout daq-release
uses: actions/checkout@v2
with:
repository: DUNE-DAQ/daq-release
path: daq-release
- name: setup dev area and checkout code
run: |
source $GITHUB_WORKSPACE/daq-buildtools/dbt-setup-env.sh
dbt-create.sh -r $GITHUB_WORKSPACE/daq-release/configs dunedaq-develop dev
cd dev
cp $GITHUB_WORKSPACE/daq-release/configs/dunedaq-develop/release_manifest.sh .
$GITHUB_WORKSPACE/daq-release/scripts/checkout-package.sh -f ./release_manifest.sh -a -b develop -o sourcecode
- name: setup build env and build the dev release
run: |
source $GITHUB_WORKSPACE/daq-buildtools/dbt-setup-env.sh
cd $GITHUB_WORKSPACE/dev
export DBT_AREA_ROOT=$PWD
export DBT_AREA_FILE="dbt-settings"
source ${DBT_AREA_ROOT}/${DBT_AREA_FILE}
setup_ups_product_areas || true
setup -B python ${dune_python_version} || true
source ${DBT_AREA_ROOT}/${DBT_VENV}/bin/activate
setup_ups_products dune_devtools || true
setup_ups_products dune_systems || true
setup_ups_products dune_externals || true
export DBT_INSTALL_DIR=${DBT_AREA_ROOT}/install
export DBT_SETUP_BUILD_ENVIRONMENT_SCRIPT_SOURCED=1
dbt-build.sh --install
nightly_tag="N$(date +%y-%m-%d)"
mkdir -p $GITHUB_WORKSPACE/nightly/${nightly_tag}
$GITHUB_WORKSPACE/daq-release/scripts/create-ups-products-area.sh -t $GITHUB_WORKSPACE/nightly/${nightly_tag}/packages
cp $GITHUB_WORKSPACE/daq-release/configs/dunedaq-develop/dbt-build-order.cmake $GITHUB_WORKSPACE/nightly/${nightly_tag}
cp $GITHUB_WORKSPACE/daq-release/configs/dunedaq-develop/pyvenv_requirements.txt $GITHUB_WORKSPACE/nightly/${nightly_tag}
$GITHUB_WORKSPACE/daq-release/scripts/upsify-daq-pkgs.py -w $GITHUB_WORKSPACE/dev -i -o $GITHUB_WORKSPACE/nightly/${nightly_tag}/packages
echo "PROGRESS: created ups products for DAQ packages."
echo " dune_daqpackages=(" >> ${DBT_AREA_ROOT}/${DBT_AREA_FILE}
echo "PROGRESS: updating dbt-settings.sh under /releases/dunedaq-develop"
cd /releases/dunedaq-develop/packages
find . -type d -name "*.version"|grep -v ups|sed 's/\.\//"/g'|sed 's/\.version/ e19:prof\"/g'|tr '/' ' '>> ${DBT_AREA_ROOT}/${DBT_AREA_FILE}
echo ")">> ${DBT_AREA_ROOT}/${DBT_AREA_FILE}
sed -i 's,.*/cvmfs/dunedaq.open," /cvmfs/dunedaq-development.opensciencegrid.org/nightly/'"$nightly_tag"'/externals,' ${DBT_AREA_ROOT}/${DBT_AREA_FILE}
sed -i 's,.*/cvmfs/dunedaq-development.open," /cvmfs/dunedaq-development.opensciencegrid.org/nightly/'"$nightly_tag"'/packages,' ${DBT_AREA_ROOT}/${DBT_AREA_FILE}
mv /releases/dunedaq-develop/externals $GITHUB_WORKSPACE/nightly/${nightly_tag}
mv ${DBT_AREA_ROOT}/${DBT_AREA_FILE} $GITHUB_WORKSPACE/nightly/${nightly_tag}/dbt-settings.sh
cd $GITHUB_WORKSPACE/nightly
tar zcvf dunedaq-${nightly_tag}.tar.gz ${nightly_tag}
rm -rf ${nightly_tag}
- name: upload nightly tarball
uses: actions/upload-artifact@v2
with:
name: nightly release
path: ${{ github.workspace }}/nightly
- name: upload build log file
uses: actions/upload-artifact@v2
with:
name: build_log
path: ${{ github.workspace }}/dev/log
```
---
### CI for DAQ packages
- <span class="blue">Runs inside `dunedaq/sl7-minimal:dev` docker container;</span>
- Use the <span class="green">**latest develop/nightly release</span>;
- <span class="red">Only build **individual DAQ package**;</span>
- CI build is triggered by:
- Push to develop;
- Pull request to develop;
- Manual trigger;
- Daily at 2:00am (CDT);
---
### CI workflow triggered by Pull request
<img src="https://i.imgur.com/8LlUitg.png" alt="CI drawing" style="width:600px;"/>
---
### CI workflow status for latest commit merged into develop
<img src="https://i.imgur.com/SO24De5.png" alt="CI drawing" style="width:600px;"/>
---
### Manually trigger a CI workflow
<img src="https://i.imgur.com/vSm5vR6.png" alt="CI drawing" style="width:600px;"/>
---
### Some details of the CI workflow
- It sets up a working directory using the develop release first;
- it *unsetup* the package itself before building;
- the build log and pre-build package is saved for 90 days on GitHub;
```yaml=
name: build-develop
# Controls when the action will run. Workflow runs when manually triggered using the UI
# or API.
on:
push:
branches: [ develop ]
paths-ignore:
- 'docs/**'
pull_request:
branches: [ develop ]
schedule:
- cron: "0 7 * * *"
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
Build_against_dev_release:
# The type of runner that the job will run on
runs-on: ubuntu-latest
container:
image: dunedaq/sl7-minimal:dev
defaults:
run:
shell: bash
env:
DBT_AREA_FILE: "dbt-settings"
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Runs a single command using the runners shell
- name: Checkout daq-buildtools
uses: actions/checkout@v2
with:
repository: DUNE-DAQ/daq-buildtools
path: daq-buildtools
- name: Checkout daq-release
uses: actions/checkout@v2
with:
repository: DUNE-DAQ/daq-release
path: daq-release
- name: setup dev area
run: |
source $GITHUB_WORKSPACE/daq-buildtools/dbt-setup-env.sh
dbt-create.sh -r /releases dunedaq-develop dev
- name: checkout package for CI
uses: actions/checkout@v2
with:
path: ${{ github.repository }}
- name: setup build env and build the dev release
run: |
export REPO=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')
source $GITHUB_WORKSPACE/daq-buildtools/dbt-setup-env.sh
cd $GITHUB_WORKSPACE/dev
dbt-setup-build-environment || true
setup_repo_env="SETUP_$REPO"
[[ -z ${!setup_env_repo+x} ]] || unsetup $REPO
cp -pr $GITHUB_WORKSPACE/DUNE-DAQ/$REPO $GITHUB_WORKSPACE/dev/sourcecode
dbt-build.sh --install
$GITHUB_WORKSPACE/daq-release/scripts/upsify-daq-pkgs.py -w $GITHUB_WORKSPACE/dev -o /tarballs
- name: upload UPS tarball and log file
uses: actions/upload-artifact@v2
with:
name: ups_package
path: /tarballs
- name: upload build log file
uses: actions/upload-artifact@v2
with:
name: build_log
path: ${{ github.workspace }}/dev/log
```
---
### Instructions of setting CI workflow for a DAQ package
1. Go to the `Actions` tab of the GitHub repo;
2. Click "set up this workflow" using the template `dunedaq-develop CI for C++`
3. Commit the workflow YAML file without change into the directory of `REPO/.github/workflows`
4. A second template which rebuilds the whole release is also available.
<span class="red">**Note: These two workflows are not to be changed by developers but release mangers.**</span>
<img src="https://i.imgur.com/EzkAojZ.png" alt="CI drawing" style="width:600px;"/>
---
## Live demo
- Let's enable CI for [`cmdlib`](https://github.com/DUNE-DAQ/cmdlib)
---
### Future improvements
* <span class="blue">**Additional workflows:**</span>
* doing clang-format linting;
* running unit tests and generating code coverage reports.
* <span class="green">**Addtional templates for developers to use:**</span>
* adding integration tests.
* Automating other parts of release making procedure (for release managers):
* generating/publishing documentations (done);
* making pypi repositories for python modules we use;
* building external dependencies.
* <span class="blue">**Self-hosted runner machines for CD:**</span>
* A server at CERN or Fermilab with cvmfs access;
* cron job with kerneros enabled for publishing to cvmfs.
---
### Conclusion
* <span class="blue">Initial nighly releases and CI for packages are ready (feedbacks are extremely welcome);</span>
* <span class="green">Additional features are on the way:</span>
* CI workflows for linting and code coverage reporting will soon be enabled;
* template for developers to add integration tests;
* <span class="red">Please make your package's develop branch **always build** at the end of day.</span>
{"metaMigratedAt":"2023-06-15T23:20:59.994Z","metaMigratedFrom":"YAML","title":"Nightly releases and Continous Integration for DUNE DAQ Software","breaks":true,"description":"View the slide with \"Slide Mode\".","contributors":"[{\"id\":\"6f8a4871-b0f4-4846-95e0-a0605fd21044\",\"add\":19411,\"del\":3975}]"}