Making a custom post-build action extension

This is an extension example for the following use case:

After performing a build for any of my releng-tool projects, I want to automatically add a series of files into the output directory before we attempt to package the contents. I want to do this using an extension to avoid the need to repeat the process across all my releng-tool projects.

Prelude

  • This extension example uses the name my-awesome-extension. Developers are free to change this with whatever name is applicable for their own extension.

  • This extension example assumes a Python 3-supported interpreter. Developers looking to support running under a Python 2 interpreter may require additional steps not covered in this tutorial.

  • This tutorial does not cover steps on publishing an extension to an index such as PyPI. Instead, steps will be provided to load a extension’s sources into the system path for releng-tool (which is optional whenever a given extension can be installed from an index or runs in an environment that already manages the installation of the extension).

Creating the post-build action extension

A first step is to setup the initial file structure for the extension. Assuming there exists a checked out releng-tool project (my-releng-tool-project) to be tested against, create a new extension folder named my-awesome-extension alongside the releng-tool project(s):

├── my-awesome-extension/
│   ├── my_awesome_extension/
│   │   ├── assets/
│   │   │   └── NOTICE.pdf
│   │   └── __init__.py
│   ├── LICENSE
│   ├── README.md
│   ...
└── my-releng-tool-project/

Inside this folder, create any base documents desired, a sample PDF, as well as preparing a my_awesome_extension Python package folder to hold the extension implementation. For the __init__.py file, add the following contents:

import os
import shutil

def releng_setup(app):
    app.connect('post-build-finished', my_awesome_postbuild_handler)

def my_awesome_postbuild_handler(env):
    print('post-build triggered!')

The above adds a function releng_setup, which releng-tool uses to register the extension into the releng-tool engine. The function is invoked during initialization by passing an application context (app) which the extension can use to hook onto events and more. This extension implements a function my_awesome_postbuild_handler, which is registered on the post-build-finished event. This allows the handler to be triggered when a post-build stage has completed for a project.

To test that the post-build event is triggered, use an existing releng-tool project and register this new example extension into the releng-tool process:

import os
import sys

...

extensions = [
    'my_awesome_extension',
]

# add local extension path into system path
container_dir = os.path.dirname(ROOT_DIR)
ext_dir = os.path.join(container_dir, 'my-awesome-extension')
sys.path.append(ext_dir)

When running releng-tool, the following message should be printed at the end of a run:

$ releng-tool
...
post-build triggered!
(success) completed (0:00:00)

Next, we can now adjust our handler to help modify the output directory when the event is triggered. In this example, we want to copy an extension-managed NOTICE.pdf file and place it into the output directory. Update the extension with the following:

def my_awesome_postbuild_handler(env):
    # find the NOTICE PDF document
    ext_dir = os.path.dirname(os.path.realpath(__file__))
    assets_dir = os.path.join(ext_dir, 'assets')
    notice_pdf = os.path.join(assets_dir, 'NOTICE.pdf')

    # copy this file into the target directory
    target = os.path.join(env['TARGET_DIR'], 'NOTICE.pdf')
    shutil.copyfile(notice_pdf, target)

With this change, a re-run of the releng-tool project should have the NOTICE.pdf document copied into the target directory for the project.

This concludes this tutorial.


For a list of available API interfaces and documentation for these interfaces, see the documentation found inside the API implementation.