CI/CD configuration reuse in OneDev
Tags: devops
Published: 2021-04-24 07:42:50

Maintaining CI/CD configuration for many projects can be complex and challenging. To reduce the overhead, [OneDev 4.3](https://onedev.io) adds the mechanism to define common CI/CD building blocks in separate projects and use/customize them in other projects.

CI/CD configuration is maintained in OneDev via build spec. When define build spec for a project, it is now possible to import build specs from other projects. Objects (jobs, services, step templates and properties) contained in imported build specs are treated as if they are defined locally, except that imported objects will be overridden by local objects with same name. In case of multiple imports, latter imported objects will override prior imported objects with same name.

With this import and overridden mechanism, you may maintain common jobs/services/step templates in a separate build spec, and use property placeholders in places where customization might be necessary. When this build spec is imported into other build specs, user may selectively override these properties to get different behaviors for different projects.

Let’s practice with an example to see how it works.

1. Start OneDev with below command in Linux or Mac:

    ```
    docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock -v $(pwd)/onedev:/opt/onedev -p 6610:6610 -p 6611:6611 1dev/server:4.3.3
    ```

2. Open browser to visit _http://localhost:6610_ to complete the setup. Add a project say _commons_, and set up its build spec as below:

    ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9nmz4yehs27ptngqgj5o.gif)

    Here we define a common CI job running a step with image specified as value of property _nodeImage_. Other projects can import this build spec and override the property to use different node image if desired. This job also defines a trigger to fire build automatically when there are new commits and property _applicable projects_ is defined to exclude the _commons_ project.

3. Now we have a common CI job. In order to reuse it in other projects, we need to add a tag. We also configure default role of the project so that everyone in the system has permission to read code for simplicity reason:

    ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/885ui86izo58tciv37uv.gif)

4. Let’s continue to add a test project, and set up its build spec to import and use the job:

    ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/43cfuakkwh2ywko7l11l.gif)

    Here we override property _nodeImage_ to use _node:14.16-buster_. Save the build spec and the imported job will be running automatically to print the expected node version.

Besides overriding property to customize imported objects, we can also use parameters to customize common step templates. Now let’s practice with this approach:

1. Continue to edit build spec of our commons project as below:

    ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/130yk3a0fyrg9a3630ul.gif)

    Here we delete objects defined previously, and add a step template instead to do the job. The template defines a parameter to get image name dynamically from caller

2. Add a new tag say _v2_ for our new version of build spec

    ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c2xf9befokzlgum9h4wb.gif)

3. Edit build spec of the test project to import the new version, add a CI job to use imported step template and specify parameter _Node Image_ as _node:14.16-buster_

    ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wevzj6q39sz8y41tf2lo.gif)

    Save the build spec to see the job running automatically to print expected node version.

Thanks for reading!