OpenFHE CI/CD Developers Guide
The GitHub Documentation is the best resource for syntax, feature detail, and abilities of the CI/CD.
In order to make modifications to reuseable workflow or actions the
CI/CD changes must be made to the [github-ci
][5] branch. This branch
is specially protected, and the OpenFHE repository uses references to
the branch for reuseable workflows and actions.
├── .github
│ ├── actions <-- Custom GitHub actions
│ │ └─ generic_workflow_builder <-- Custom GitHub actions to bootstrap the build
│ │ └── action.yml <-- Custom action file, defines the steps for a given configuration, cmake -> build -> unittest
│ ├── workflows <-- GitHub workflows(pipelines)
│ └── generic_workflow.yml <-- A reuseable workflow that handles the default builds and tests the important configurations, uses generic_workflow_builder/action.yml
For changes to what happens for the Main, Manual, or Pull-Request the files must be updated on the main branch.
├── .github
│ ├── workflows <-- GitHub workflows(pipelines)
│ ├── main.yml <-- Runs when a branch is merged to main, uses generic_workflow
│ ├── manual.yml <-- Runs on-demand with parameters, uses generic_workflow
│ ├── pull-request.yml <-- Runs when a pull-request to main is created, uses generic_workflow
Actions
GitHub Actions are used to create function like abilities to the CI/CD. Thus reducing the scripting, lines of code, and complexity of the workflows. There is currently a single action to help build and test a given configuration .github/actions/generic_workflow_builder/action.yml.
Generic Workflow Builder
This builder handles the setup, build, and running of binaries
(such as unittests) for a single configuration. The flow of
the Generic Workflow Builder
actions is:
Cmake configuration based on inputs
Build the configuration
Run unittests on the configuration
The actions are flexible as when can pass inputs
which can be seen
in first section of the
.github/actions/generic_workflow_builder/action.yml.
These inputs can be used throughout the action.yml to change behaviour.
Note
For more info on GitHub Actions in general please visit Learn GitHub Actions. The remainder of the action description will be specific to our implementation and use of GitHub Action features.
Current Action Inputs
We currently have the following inputs supported:
module_name - friendly string identifier for the configuration
cmake_args - string with all arguments set up in the calling workflow
Adding New Inputs
To add a new input to the action it will need to be added to the
inputs
section in the
.github/actions/generic_workflow_builder/action.yml.
There is a constraint of 10 inputs, so care needs to be taking when
selecting inputs. Select that the type of the input for your input and
choose a default value that will not alter the previous behavior of the
important workflows After adding the parameter to
action.yml
you must set it using the with
field, shown below, in any workflow
that you want to use the new parameter.
Defining a new input
name: 'Generic Workflow Builder'
inputs:
my_new_input:
description: "Example of how to add a new input to the action"
type: string
default: ''
Using the input
uses: ./.github/actions/generic_workflow_builder
with:
module_name: ${{ github.job }}
# ...
my_new_input: 'Do something new!'
Using the input value in the action procedure
runs:
# ...
run: |
echo "New input has value: ${{inputs.my_new_input}}"
The ${{}}
is how the procedure can access the passed in value
Workflows
When designing the workflows for OpenFHE we took the approach of bundling multiple configurations together. This influenced how the action.yml was designed, as we want to have the server configure, build, and run outputs without needing to pass artifacts around. Previously we had done all the builds for every configuration, then ran all the unittests for all the configurations, etc. This required over 20GB of artifacts be passed around. This means that each conifguration must build and pass all tests before another build can be evaluated.
Currently the default build always runs, and the other builds depend on it. Even when the other workflow jobs are off.
Note
For more general information on GitHub Workflows please visit Using Workflows
There are 3 custom and one reuseable workflows:
Main - To extensively test pushes to the main branch and publish docs.
Manual - To do a batch of builds with a control over compilers, native size, configurations.
Pull-Request - To test any pull-requests generated, this tests a healthy number of configurations but is not as extensive as Main.
Generic/Reuseable Workflow - To be called by any custom workflow.
They all allow to select a number of options that are supported and worth testing on a server.
NOTE: ALL the options for Manual must exist in both properties on.workflow_call.inputs
and on.workflow_dispatch.inputs
.
It is necessary as Manual calls a reuseable workflow.
As Main and Pull-Request are kicked off automatically and all their input options are hardcoded
in the job
section under the with
property.
Note
There is a limit of 10 inputs.
There are two important JSON maps used in the workflows:
cmake_args_map - maps the job name to the job’s specific set of cmake arguments (3 custom workflows only)
COMPILERS_MAP - converts the input Compiler Type to a string with cmake arguments to set the compiler for C and C++ (generic_workflow only)
Warning
Before adding a new compiler option developers must ensure that the server has the compiler installed and the cmake arguments specifying that compiler’s path are correctly set in the JSON map.
example: passing a JSON map as an input to generic_workflow.yml
jobs:
call:
uses: openfheorg/openfhe-development/.github/workflows/generic_workflow.yml@github-ci
with:
# ...
# cmake_args_map holds job specific additional cmake options. compiler flags, native_backend flag and
# OpenMP flag are set in generic_workflow.yml
cmake_args_map: '{
# ...
"mb2" : "-DBUILD_EXTRAS=ON -DMATHBACKEND=2",
"mb2_tcm" : "-DBUILD_EXTRAS=ON -DMATHBACKEND=2 -DWITH_TCM=ON",
# ...
"mb6_ntl_debug_tcm" : "-DBUILD_EXTRAS=ON -DMATHBACKEND=6 -DWITH_NTL=ON -DWITH_TCM=ON -DCMAKE_BUILD_TYPE=Debug",
}'
Warning
The map’s keys are not linked to the inputs options, this must be manually kept in sync.
Pull-Request Workflow
The pull-request.yml defines the Pull-Request Workflow, which runs when a pull request is opened or reopened or when the head branch of the pull request is updated. Currently it is setup to run on the main branch only. This is defined by the following code snippet.
on:
pull_request:
branches:
- main
The Pull-Request Workflow calls Generic/Reuseable Workflow and
runs all jobs with NATIVE_SIZE=128
and GCC
only.
Main Workflow
The main.yml defines the Main Workflow, which runs when changes are pushed to the main branch.
on:
push:
branches:
- main
The Main Workflow calls Generic/Reuseable Workflow and runs all jobs with all native backends and with both GCC and CLANG. And lastly this workflow has a job that pushes the doxygen generated documentation to a specific branch, gh-pages in the repository.
Manual workflow
The manual workflow allows for more configurations to be tested and the flexibility to test unique combinations of the compiler, NativeInteger sizes and jobs.
Generic/Reuseable Workflow
The generic_workflow.yml
defines the reuseable workflow, which is not run directly through GitHub
pushes, pull-requests, or UI interactions. Instead this workflow encapuslates the bulk of the CI/CD that should be used
in multiple workflows. This workflow is declared reuseable by the following code snippet:
on:
workflow_call:
inputs:
# ...
Where workflow_call
property enables other workflows to run this entire workflow through the following calling squence:
jobs:
call:
uses: openfheorg/openfhe-development/.github/workflows/generic_workflow.yml@github-ci
with:
# ...
The workflow makes use of the Generic Workflow Builder to run a number of configurations that correspond to
the workflow’s inputs
.
Inputs
MATHBACKEND2 jobs: mb2, mb2_tcm, mb2_debug, all, none
MATHBACKEND4 jobs: mb4, mb4_tcm, mb4_debug, all, none
MATHBACKEND6 jobs: mb6_ntl, mb6_ntl_tcm, mb6_ntl_debug_tcm, all, none
Each of these inputs
enables or disables the corresponding job(s). Just a reminder that one job
default
is always implicitly enabled.
Compiler Selection
Selecting the compiler is a bit convoluted, the JSON syntax is used to create a map between compilers and
the cmake options to use the compiler selected. This map uses the workflow_call.inputs.compiler
as the key in
.github/workflows/generic_workflow.yml.
and the cmake equivalent option as the value.
Note
This is linked by the definition of COMPILERS_MAP in the jobs
Modifying the compiler input will require modification of env.COMPILERS_MAP
- Getting cmake compiler options can’t be done in the .github/actions/generic_builder/action.yml,
as access to the
fromJson
function isn’t available in that scope.
Below is a part of the existing map using the >-
operator for multiple lines:
Compiler map definition
COMPILERS_MAP: >-
{
# ...
"GCC-11" : "-DCMAKE_CXX_COMPILER=/usr/bin/g++-11 -DCMAKE_C_COMPILER=/usr/bin/gcc-11",
# ...
"CLANG-14" : "-DCMAKE_CXX_COMPILER=/usr/bin/clang++-14 -DCMAKE_C_COMPILER=/usr/bin/clang-14"
}
Modifying or Adding New Workflows
When developing a new workflow it is required that the Default Branch be set to whatever
your development branch is to expose the workflows, and thus reverted on completion.
This can be done by navigating to the repository’s Settings > Branches
and selecting
a new Default Branch as shown below.
When modifying an existing workflow then you should test the changes on your feature branch. The feature branch can be picked from the “Use workflow from” drop-down menu for Manual or can be hardcoded for testing for Main or Pull-Request.
Please take care with naming new workflows - Follow the design pattern already in use, where the Workflows name and the corresponding YML file are related via the pattern:
YML File: new-workflow.yml
Workflow Name:
name: New Workflow
Setup GitHub Actions Runner
Setup Linux Server for OpenFHE
OpenFHE To see how to setup linux_platform_packages.sh in the repository, or run it on your linux platform.
Note
This is for an Ubuntu 22.04 distribution
Launch an EC2 Instance using AWS CLI
aws ec2 run-instances \
--image-id <AMI-Id> \
--count 1 \
--instance-type <EC2-Type> \
--key-name <Key-Pair-Name> \
--subnet-id <Subnet> \
--security-group-ids <Security-Group-ID>
--user-data file://user-data.txt
This will create an EC2 instance.
Configure the EC2 Instance as GitHub Actions Runner
Refer this documentation, adding-self-hosted-runners, on how to self-hosted runner to a repository. Below is an image of how to verify that a self-hosted runner is linked to the repository.