This repository was archived by the owner on Apr 7, 2025. It is now read-only.
[RFD - 0004] - Semaphore Packages #70
AleksandarCole
started this conversation in
RFD
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
[RFD - 0004] - Semaphore Packages
@radwo
@DamjanBecirovic
@lucaspin
Draft
Table of Contents
What
Semaphore Packages are a framework designed to create and share common CI/CD elements between your pipelines. They enable developers to encapsulate repeatable steps, configurations, and scripts into reusable packages. These packages can be versioned, maintained, and distributed across multiple projects.
Why
Key concerns solved by Semaphore Packages:
Functionality
Overview
Packages are modeled after code libraries, where a set of pre-defined functionality can be included in an application. Similarly, Semaphore Packages are a set of pre-defined CI/CD components.
A Semaphore package is a collection of steps, blocks, and pipelines that can be imported into a pipeline.
An example Semaphore Package that exports a complex Android Emulator step is defined with:
The above YAML configuration defines steps for changing the Android emulator version.
This package can be included in your YAML definition with:
Using Semaphore Packages
Using public packages from the official registry
The official package registry contains a set of officially supported packages that you can use in your pipelines.
Packages include steps for working with major frameworks (ex. Rails, Express, React), language-specific steps (ex. Go, Rust), and common steps for deployment (ex. GCP, AWS, Heroku).
The official packages are name spaced under the
semaphoreci/*
namespace.An example pipeline that uses the official Rails package to include blocks for running Rubocop, Brakeman, RSpec, and Cucumber would be specified with this YAML:
Using third-party open-source packages
The official registry also hosts third party packages, contributed by third-party developers.
Third-party packages are name spaced under the name of the contributor
<name>/*
.An example pipeline that uses third-party packages developed by
jimbo
that exports CI metrics to DataDog are imported like in the following example:Using organization level private packages
Every organization has a private package namespace accessible only by pipelines in that organization. Private Packages are ideal for modeling internal conventions and reusing common CI/CD elements between your projects.
Packages in the organization are not namespaced.
An example package that exports a common CI/CD steps for Lint, Unit, and Security Scans for microservices can be used with:
Using local packages from your repository
Packages can be included directly from the repository. Local Packages are ideal for abstracting parts of the pipeline, keeping the main pipeline shorter and more concise.
An example package that export steps for deployment can be used with:
The package in the above example is imported from a location relative to the Pipeline YAML. If the Pipeline YAML is in
.semaphore/prod.yml
, the include path./deployment/k8s.yml
will load it from.semaphore/deployment/k8s.yml
.To access a package relative to the root of the repository, start the from stanza with
/
:The package is loaded from
<repo-root>/ci_package/k8s.yml
.Customizing imported CI/CD elements
The included packages can be customized to fit the need of the current pipeline. Packages allow three types of customization:
Passing arguments to imported steps, blocks, and pipelines
Every package can define a set of arguments.
Arguments enable package creators to receive configuration options. For package users, this is the primary way of customizing the CI/CD element.
In the following example, we will use the Golang package and customize the Test block to run tests with verbose output:
Customizing by overriding configuration
Apart from passing arguments, the package users can also opt for overriding stanzas in the included blocks.
In the following example, we will override the Heroku deployment block's prologue steps to execute several steps before running the deployment and inject deployment secrets.
Passing arguments to the whole package
Package level arguments allow you to pass values to every exported CI/CD element.
In the following example, we will use the goRoot argument that will be applied on every exported element from that package:
Creating a Semaphore Package
Creating your first package
Semaphore Packages are a collection of steps, blocks, and pipelines that can be used in your CI/CD pipelines.
In this example, we are constructing a barebone Hello World package. When included in a pipeline, the block will print a message in the output.
Create a .semaphore/packages/hello.yml file with the following content:
We have created our first package!
To use it in a pipeline, include it in your Semaphore YAML configuration:
Exporting CI/CD components
The Hello World package demonstrated how to export a step from a package. Steps are the simplest construction elements, but they are not the only onse.
Semaphore Packages allow you to export three types of elements. Steps, Blocks, and Pipelines.
StartDatabase, StartWebserver, ChangeFirefoxVersion, RunTest.
tests", "execute static code analysis", "release a docker image".
of "blue-green deployment", "CI steps".
To explore the whole suite of options, we will write a Heroku package from scratch.
Exporting steps
Start by creating a
./semaphore/packages/heroku.yml
in your repository.We have set up the base of our new package for managing Heroku applications.
Time to export some Heroku specific steps from the
./semaphore/packages/heroku.yml
package.To use these steps, you can include them into the pipeline:
Exporting Blocks
Steps offer the most flexibility, but they require a bit of know-how to use in your pipelines. To bundle and export our steps into a bigger logical chunk, we can use blocks.
Going back to our
.semaphore/package/heroku.yml
and combining our steps into blocks:To use them in a Pipeline:
Exporting Pipelines
To go even a level beyond, we can combine and export a full pipeline to our users.
This option is the fastest to use but offers the least amount of flexibility.
To use it in our pipelines:
Types of Arguments
The Semaphore Packages framework accepts the following argument types:
Some argument types can provide optional validation parameters:
Integers
Integers can set a valid range of values. For example:
String
Strings can set a minimal and maximal length. For example:
Strings can also set a regex validation pattern:
Strings can also define a list of valid values:
Publishing packages
A central package registry allows fast access to a broad set of Semaphore Packages. Packages are developed in a Git repository and published to the registry.
Publishing an open-source package to the Package Registry
To publish a package to the registry, execute the following command:
To verify that the package was uploaded, execute:
To verify that the package details are correct, execute:
$ sem describe package hello PACKAGE Name: HelloWorld Version: v1.1 Display Hello World with a custom message. USAGE 1) Install the package include: - name: HelloWorld from: shiroyasha/hello 2) Use the hello world block to display a message blocks: - name: Hello use: HelloWorld.Display params: message: Hello Hello Hello EXPORTED BLOCKS 1) Display - Displays a message on the command line Params: - message - The message to display, default: Hello World, type: string
Adding a private package to your Semaphore organization
Publishing a private — organization scoped package — is analogues to publishing a public package.
To publish a package to the registry, execute the following command:
To verify that the package was uploaded, execute:
To verify that the package details are correct, execute:
$ sem describe package hello PACKAGE Name: HelloWorld Version: v1.1 Display Hello World with a custom message. USAGE 1) Install the package include: - name: HelloWorld from: hello 2) Use the hello world block to display a message blocks: - name: Hello use: HelloWorld.Display params: message: Hello Hello Hello EXPORTED BLOCKS 1) Display - Displays a message on the command line Params: - message - The message to display, default: Hello World, type: string
New CI/CD concepts
The introduction of Semaphore Packages comes bundled with a handful of new CI/CD
concepts.
Steps
Steps are the new atomic instructions in a CI/CD pipeline. They are a generalization of commands and aim to resolve the shortcomings of the current system.
A step can be a simple bash command:
It can also be a multiline command with a name:
Bash is not the best tool for every CI/CD step. For example, managing maps is notoriously hard in Bash. Steps can use a custom scripting language, for example, Ruby:
Sub-Pipelines
Sub-pipelines reduce the overhead of managing complex projects with many interconnected blocks. Nowhere is this more apparent than in Monorepo projects with multiple services triggered with a change_in filter.
A use case is demonstrated in the next example that uses sub-pipelines to define steps for each service in a monorepo context:
YAML Compilation
Semaphore aims to remain transparent and easy to debug. With Semaphore Packages, the YAML fetching and compilation steps are exposed in the
init job
.In case of problems, the developer can peak into the compilation logs and trace out if a dependency is causing problems.
Package Registry/Inventory
🔧 work in progress 🔧
Functional requirements for public and private package registries as well as details on versioning, packages documentation and package structure are to be described here.
UI integration
🔧 work in progress 🔧
UI/UX updates for integration with the Workflow Builder and UI design of the Packages Registry/Inventory to be described here.
Security
🔧 work in progress 🔧
Security requirements, architecture and threat assessment to be described here.
Beta Was this translation helpful? Give feedback.
All reactions