0x00 Abstract

I used to be a Java/PHP/PolymerJS developer for 2 years before joining the wonderful information security industry and developing in C/C++ and C#. I’m probably not a great programmer but a least I’m documenting my code! Trust me, well documented code will save your butt.

I have subscribed to a professional GitHub account few weeks back, which gave me access to the 3000 minutes of GitHub Actions per months. GitHub Action is awesome because this allow developers to create custom software development life cycle (SDLC) workflows, directly from GitHub. For each workflow you can define custom jobs and tasks.

My plan was to use GitHub Actions to automatically generate and deploy Doxygen documentation when I push code to a master branch. In our case we will have one job with two tasks. To archive that, I am using the following GitHub Actions: mattnotmitt/doxygen-action@v1.1.0; and peaceiris/actions-gh-pages@v3 First one will be used to generate the HTML documentation by parsing the source code with Doxygen. Second one will deploy the HTML documentation to a GitHub page to make the documentation public.

You can find an example with this project: https://github.com/am0nsec/SharpHellsGate

0x01 Initial Steps

First, you need to properly comment your code with notations that can be parsed by Doxygen. Note that Doxygen support multiple languages like, C, C++, C# and even Python (gross). In my case, I used the XML documentation comments, as recommended by Microsoft for C# projects.

Example of method documentation using the XML documentation comments in C#:

/// <summary>
/// Extract the byte representation of a structure from the memory stream.
/// </summary>
/// <typeparam name="T">The Type of the structure to extract from the memory stream.</typeparam>
/// <param name="offset">The location of the structure in the memory stream.</param>
/// <returns>The structure as byte span.</returns>
protected Span<byte> GetStructureBytesFromOffset<T>(Int64 offset) where T : struct

Once you have your code ready to be deployed, you can create a new git orphan branch and remove everything in the branch. Previous commits are not required because the branch will only be used for the documentation, hence the orphan branch:

git checkout --orphan gh-pages
git rm -rf .
git commit --allow-empty -m "init"
git push origin gh-pages

0x02 Doxygen Configuration

To generate the HTML documentation, Doxygen will parse the source code but will also request a configuration file. In my case, I named the file Doxyfile. The configuration file is quite lengthy, so I recommend using the doxygen binary to generate a template.

sudo apt install doxygen -y
doxygen -g Doxyfile

As mentioned hereabove, the configuration file is huge and contains something like ~400 different options. Fortunately for us, there is only few options that require our attention. I am not going to go through them one by one because names are pretty self-explanatory. You have to change the values based on your project.

PROJECT_NAME           = "Shap Hell's Gate"
PROJECT_NUMBER         = 1.0
PROJECT_BRIEF          = "C# Implementation of the Hell's Gate VX Technique"
OUTPUT_DIRECTORY       = ./doc/
OUTPUT_LANGUAGE        = English
GENERATE_LATEX         = NO
EXTRACT_ALL            = YES
INPUT                  = .
RECURSIVE              = YES

0x03 GitHub Actions

Now that everything is ready, the last step is to create a new Workflow. First thing, create the folder in which GitHub will look up the workflows.

mkdir -p .github/workflows/
Within this directory you can create a YAML file, which will represent a new workflow:

name: Documentation

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches: [ master ]

jobs:
  build-documentation:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    
    # Build the HTML documentation
    - name: Doxygen Action
      uses: mattnotmitt/doxygen-action@v1.1.0
      with:
          doxyfile-path: ./Doxyfile
          working-directory: .
    
    # Deploy the HTML documentation to GitHub Pages
    - name: GH Pages Deployment
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./doc/html/
        enable_jekyll: false
        allow_empty_commit: false
        force_orphan: true
        publish_branch: gh-pages

This YAML file, will create a new Workflow named Documentation. This workflow will execute two tasks. The first one named Doxygen Action will be responsible for installing doxygen and generate the HTML documentation. The second tasks named GH Pages Deployment will deploy the HTML documentation to the gh-pages branch, which will then be used by GitHub Pages.

If the build succeeds, you should have something like that:

Final step is to set the branch that will be used by GitHub Pages. The source branch can be change in the settings of your repository.