.. role:: htm(raw) :format: html .. role:: pdf(raw) :format: latex pdflatex .. _Ocelot: https://github.com/ThreeMammals/Ocelot .. _Cake: https://cakebuild.net .. _Bash: https://www.gnu.org/software/bash .. _build.cake: https://github.com/ThreeMammals/Ocelot/blob/main/build.cake .. _GitHub Actions: https://docs.github.com/en/actions .. _NuGet: https://www.nuget.org/profiles/ThreeMammals Building ======== This document summarises the build and release process for the `Ocelot`_ project. The build scripts are written using `Cake`_ (C# Make), with relevant build tasks defined in the '`build.cake`_' file located in the root of the `Ocelot`_ project. The scripts are designed to be run by developers locally in a `Bash`_ terminal (on any OS), in Command Prompt (CMD) or PowerShell consoles (on Windows OS), or by a CI/CD server (currently `GitHub Actions`_), with minimal logic defined in the build server itself. The final goal of the build process is to create ``Ocelot.*`` `NuGet`_ packages (.nupkg files) for redistribution via the `NuGet`_ repository or manually. The build process consists of several steps: (1) compilation, (2) testing, (3) creating and publishing `NuGet`_ packages, and (4) making an official GitHub release. The build process requires pre-installed .NET SDKs on the build machine (host) for all target framework monikers: TFMs are ``net8.0`` and ``net9.0`` currently. In general, the build process is the same across all environments and tools, with a few differences described below. .. _b-in-ide: In IDE ------ .. _Release configuration: https://learn.microsoft.com/en-us/visualstudio/debugger/how-to-set-debug-and-release-configurations?view=vs-2022 In an IDE, a DevOps engineer can build the project in Visual Studio IDE or another IDE in `Release configuration`_ mode, but the latest .NET 8/9 SDKs must be pre-installed on the local machine. However, this approach is not practical because the generated '.nupkg' files must be uploaded to `NuGet`_ manually, and the GitHub release must also be created manually. A better approach is to utilize the '`build.cake`_' script :ref:`b-in-terminal`, which covers all building scenarios. .. _b-in-terminal: In terminal ----------- .. _./: https://github.com/ThreeMammals/Ocelot/tree/main/ Folder: `./`_ These are local machine or remote server building scenarios using build scripts, aka '`build.cake`_'. In these scenarios, the following two commands should be run in a terminal from the project's root folder: .. code-block:: shell dotnet tool restore && dotnet cake # In Bash terminal dotnet tool restore; dotnet cake # In PowerShell terminal .. _break: http://break.do **Note**: The default target task ("Default") is "Build", and output files will be stored in the ``./artifacts`` directory. To run a desired target task, you need to specify its *name*: .. code-block:: shell dotnet tool restore && dotnet cake --target=name # In Bash terminal dotnet tool restore; dotnet cake --target=name # In PowerShell terminal For example, - .. code-block:: shell dotnet cake --target=Build It runs a local build, performing compilation and testing only. - .. code-block:: shell dotnet cake --target=Version It checks the next version to be tagged in the Git repository during the next release, without performing compilation or testing tasks. - .. code-block:: shell dotnet cake --target=CreateReleaseNotes It generates Release Notes artifacts in the ``/artifacts/Packages`` folder using the ``ReleaseNotes.md`` template file. - .. code-block:: shell dotnet cake --target=Release It creates a release, consisting of the following steps: compilation, testing, generating release notes, creating .nupkg files, publishing `NuGet`_ packages, and finally, making a GitHub release. .. _dotnet-tools.json: https://github.com/ThreeMammals/Ocelot/blob/main/.config/dotnet-tools.json **Note 1**: The building tools for the ``dotnet tool restore`` command are configured in the `dotnet-tools.json`_ file. **Note 2**: Some targets (build tasks) require appropriate environment variables to be defined directly in the terminal session (aka secret tokens). .. _b-with-docker: With Docker ----------- .. _docker: https://github.com/ThreeMammals/Ocelot/tree/main/docker .. _Dockerfile.build: https://github.com/ThreeMammals/Ocelot/blob/main/docker/Dockerfile.build .. _24.0: https://github.com/ThreeMammals/Ocelot/releases/tag/24.0.0 Folder: ./`docker`_ The best way to replicate the CI/CD process and build `Ocelot`_ locally is by using the `Dockerfile.build`_ file, which can be found in the '`docker`_' folder in the `Ocelot`_ root directory. For example, use the following command: .. code-block:: shell docker build --platform linux/amd64 -f ./docker/Dockerfile.build . You may need to adjust the platform flag depending on your system. **Note**: This approach is somewhat excessive, but it will work if you are a masterful Docker user. 🙂 The Ocelot team has not followed this approach since version `24.0`_, favoring :ref:`b-with-ci-cd`-based builds and occasionally building :ref:`b-in-terminal` instead. .. _b-with-ci-cd: With CI/CD ---------- .. _workflows: https://github.com/ThreeMammals/Ocelot/tree/main/.github/workflows .. _PR: https://github.com/ThreeMammals/Ocelot/actions/workflows/pr.yml .. _Develop: https://github.com/ThreeMammals/Ocelot/actions/workflows/develop.yml .. _Release: https://github.com/ThreeMammals/Ocelot/actions/workflows/release.yml .. _Coveralls: https://coveralls.io .. |ReleaseButton| image:: https://github.com/ThreeMammals/Ocelot/actions/workflows/release.yml/badge.svg :target: https://github.com/ThreeMammals/Ocelot/actions/workflows/release.yml :alt: Release Status :class: img-valign-textbottom .. |DevelopButton| image:: https://github.com/ThreeMammals/Ocelot/actions/workflows/develop.yml/badge.svg :target: https://github.com/ThreeMammals/Ocelot/actions/workflows/develop.yml :alt: Development Status :class: img-valign-textbottom .. |DevelopCoveralls| image:: https://coveralls.io/repos/github/ThreeMammals/Ocelot/badge.svg?branch=develop :target: https://coveralls.io/github/ThreeMammals/Ocelot?branch=develop :alt: Coveralls Status :class: img-valign-textbottom .. |ReleaseCoveralls| image:: https://coveralls.io/repos/github/ThreeMammals/Ocelot/badge.svg?branch=main :target: https://coveralls.io/github/ThreeMammals/Ocelot?branch=main :alt: Coveralls Status :class: img-valign-textbottom .. _break2: http://break.do | Folder: ./.github/`workflows`_ | Provider: `GitHub Actions`_ | Workflows: `PR`_, `Develop`_, `Release`_ | Dashboard: `Workflow runs `_ (Actions tab) The `Ocelot`_ project utilizes `GitHub Actions`_ as a CI/CD provider, offering seamless integrations with the GitHub ecosystem and APIs. Starting from version `24.0`_, all pull requests, development commits, and releases are built using `GitHub Actions`_ workflows. There are three `workflows`_: one for pull requests (`PR`_), one for the ``develop`` branch (`Develop`_), and one for the ``main`` branch (`Release`_). **Note**: Each workflow has a dedicated status badge in the `Ocelot README`_: the |ReleaseButton|:pdf:`\href{https://github.com/ThreeMammals/Ocelot/actions/workflows/release.yml}{Release}` button and the |DevelopButton|:pdf:`\href{https://github.com/ThreeMammals/Ocelot/actions/workflows/develop.yml}{Develop}` button, with the `PR`_ status being published directly in a pull request under the "Checks" tab. The `PR`_ workflow will track code coverage using `Coveralls`_. After opening a pull request or submitting a new commit to a pull request, `Coveralls`_ will publish a short message with the current code coverage once the top commit is built. Considering that `Coveralls`_ retains the entire history but does not fail the build if coverage falls below the threshold, all workflows have a built-in 80% threshold, applied internally within the ``build-cake`` job, particularly during the "`Cake Build`_" step-action. If the code coverage of a newly opened pull request drops below the 80% threshold, the `'build-cake' job`_ will fail, logging an appropriate message in the "`Cake Build`_" step. **Note 1**: There are special code coverage badges in `Ocelot README`_: the `Develop`_ |DevelopCoveralls| button and the `Release`_ |ReleaseCoveralls| button. **Note 2**: The current code coverage of the `Ocelot`_ project is around 85-86%. The coverage threshold is subject to change in upcoming releases. All `Coveralls`_ builds can be viewed by navigating to the `ThreeMammals/Ocelot `_ project on Coveralls.io. Documentation ------------- .. _docs: https://github.com/ThreeMammals/Ocelot/tree/main/docs .. _.readthedocs.yaml: https://github.com/ThreeMammals/Ocelot/blob/main/.readthedocs.yaml .. _Read the Docs: https://about.readthedocs.com .. _Ocelot app: https://app.readthedocs.org/projects/ocelot/ .. _README: https://github.com/ThreeMammals/Ocelot/blob/main/docs/readme.md .. _Ocelot README: https://github.com/ThreeMammals/Ocelot/blob/main/README.md .. |ReleaseDocs| image:: https://readthedocs.org/projects/ocelot/badge/?version=latest&style=flat-square :target: https://app.readthedocs.org/projects/ocelot/builds/?version__slug=latest :alt: ReadTheDocs Status :class: img-valign-middle .. |DevelopDocs| image:: https://readthedocs.org/projects/ocelot/badge/?version=develop&style=flat-square :target: https://app.readthedocs.org/projects/ocelot/builds/?version__slug=develop :alt: ReadTheDocs Status :class: img-valign-middle .. _break3: http://break.do | Folder: ./`docs`_ | Dashboard: `Ocelot app`_ project Documentation building is configured using the '`.readthedocs.yaml`_' integration file, which allows builds to run separately via the `Read the Docs`_ publisher. All build artifacts and document sources are located in the '`docs`_' folder. More details on the documentation build process can be found in the `README`_. **Note 1**: Documentation builds have a dedicated status badges in `Ocelot README`_: the `Develop`_ |DevelopDocs| button and the `Release`_ |ReleaseDocs| button. **Note**: Documentation can be easily built locally in a terminal from the '`docs`_' folder by running the ``make.sh`` or ``make.bat`` scripts. The resulting documentation build files will be located in the ``./docs/_build`` folder, with the HTML documentation specifically written to the ``./docs/_build/html`` folder. .. _b-testing: Testing ------- The tests should run and function correctly as part of the *building* process using the ``dotnet test`` command. You can also run them in Visual Studio IDE within the Test Explorer window. Depending on your build scenario, `Ocelot`_ *testing* can be performed as follows. :ref:`b-in-ide`: Simply run tests via the Test Explorer window of Visual Studio IDE. :ref:`b-in-terminal`: There are two main approaches: 1. Run the ``dotnet test`` command to perform all tests (unit, integration, and acceptance): .. code-block:: shell dotnet test -f net8.0 ./Ocelot.sln Or run tests separately per project: .. code-block:: shell dotnet test -f net8.0 ./test/Ocelot.UnitTests/Ocelot.UnitTests.csproj # Unit tests only dotnet test -f net8.0 ./test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj # Integration tests only dotnet test -f net8.0 ./test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj # Acceptance tests only 2. Run ``dotnet cake`` command: ``dotnet cake --target=Tests`` to perform all tests (unit, integration and acceptance). Or run tests separately per *testing* project: .. code-block:: shell dotnet cake --target=UnitTests # unit tests only dotnet cake --target=IntegrationTests # integration tests only dotnet cake --target=AcceptanceTests # acceptance tests only :ref:`b-with-docker`: This approach is not recommended. Instead, perform automated testing :ref:`b-with-ci-cd` or opt for :ref:`b-in-terminal`-based testing, which is a more advanced method. :ref:`b-with-ci-cd`: In `GitHub Actions`_ `workflows`_, the *testing* process consists of separate testing steps, organized per job: * In the `'build' job`_: There are '`Unit Tests`_', '`Integration Tests`_', and '`Acceptance Tests`_' steps. * In the `'build-cake' job`_: There is a '`Cake Build`_' step responsible for performing tests internally. .. _'build' job: https://github.com/search?q=repo%3AThreeMammals%2FOcelot+build%3A+path%3A%2F%5E%5C.github%5C%2Fworkflows%5C%2F%2F&type=code .. _Unit Tests: https://github.com/search?q=repo%3AThreeMammals%2FOcelot+%22Unit+Tests%22+path%3A%2F%5E%5C.github%5C%2Fworkflows%5C%2F%2F&type=code .. _Integration Tests: https://github.com/search?q=repo%3AThreeMammals%2FOcelot+%22Integration+Tests%22+path%3A%2F%5E%5C.github%5C%2Fworkflows%5C%2F%2F&type=code .. _Acceptance Tests: https://github.com/search?q=repo%3AThreeMammals%2FOcelot+%22Acceptance+Tests%22+path%3A%2F%5E%5C.github%5C%2Fworkflows%5C%2F%2F&type=code .. _'build-cake' job: https://github.com/search?q=repo%3AThreeMammals%2FOcelot+%22-cake%3A%22+path%3A%2F%5E%5C.github%5C%2Fworkflows%5C%2F%2F&type=code .. _Cake Build: https://github.com/search?q=repo%3AThreeMammals%2FOcelot+%22cake-build%2F%22+path%3A%2F%5E%5C.github%5C%2Fworkflows%5C%2F%2F&type=code SSL certificate --------------- To create a certificate for :ref:`b-testing`, you can use `OpenSSL `_: * Install the `openssl `__ package (if you are using Windows, download the binaries `here `_). * Generate a private key: .. code-block:: bash openssl genrsa 2048 > private.pem * Generate a self-signed certificate: .. code-block:: bash openssl req -x509 -days 1000 -new -key private.pem -out public.pem * If needed, create a PFX file: .. code-block:: bash openssl pkcs12 -export -in public.pem -inkey private.pem -out mycert.pfx