Package

Montuer natively facilitates the Package CI Job with the sole purpose to pack various variants of the application or libraries for various platform system deployments. This job is mainly for executing consistent packaging whenever and whereever is needed easily and seamlessly.

The objective of the job is simple: to execute all packaging for various deployments seamlessly and consistently on a single host machine with minimal to no further instructions.

Overall Configurations

To configure the job for execution, you need to supply and modify .configs/monteur/package/config.toml file. These are the various settings for customizations.

[Variables]

To configure job-wide variables for all packaging tasks, you can include or modify the existing [Variables] table. Here is an example:

1
2
[Variables]
TestArguments = "--verbose"

This table only accepts Plain Variables Definition.

The values can be any data types as long as it is sensible for direct replacement in a variable formatting activities.

[FMTVariables]

To configure job-wide formattable variables for all packaging tasks, you can include or modify the existing [FMTVariables] table. Here is an example:

1
2
[FMTVariables]
MainDir = '{{- .RootDir -}}/gopkg'

This table accepts Formattable Variables Definition (e.g. {{- .Version -}}).

These variables shall be processed after the [Variables] table and all the formatting clauses shall be replaced with the given variables. The processed Key-Value output data shall then be backfilled either create or overwrite back into [Variables] table depending on its Key-Value existence.

Packages' Configurations

Monteur accepts one packaging recipes file per packaging variant (e.g. one deb.toml for linux-amd64, linux-arm64, linux-riscv, and etc). However, the internal operations allow many packaging recipes file to run simultenously and asynchonously (e.g. deb.toml, appimage.toml, targz.toml, …). Each configuration file shares the same file structure.

Storing Location

All packaging recipe configuration files SHALL be stored inside .configs/monteur/package/jobs directory.

File Nature

The configuration file MUST have the file extension. Otherwise, it will be ignored. Currently the following formats are supported and sorted by priority sequences:

  1. TOML (recipe.toml) - https://github.com/toml-lang/toml

The filename does not affect any of the parsed configurations so feel free to name it according to your own pattern. Monteur recommends using packaging recipe name to keep sorting work sane. Example: deb.toml for all .deb packages.

Data Structure

Each configuration file follows the following data structure:

[Metadata]

This table houses all the information about the packaging recipe metadata such as its name, description, and its supported types. Here is an example:

1
2
3
4
5
Name = 'DEB'
Description = """
Package monteur into .deb package file using manual commands.
"""
Type = 'deb-manual'

The Name field will be used for various internal configurations for Monteur’s packaging recipe identifications and logging purposes.

The Description is mainly for logging and the config file comprehension purposes. You can write a short description for it.

The Type is the type of supported packaging modes for Monteur to execute the recipes. The currently supported modes are:

[Variables]

This table houses all Plain Variables Definition specific to this packaging recipes. It shall appears onto all listed packages. Example:

1
2
3
4
5
[Variables]
GPGID = '[email protected]'
GPGExistence = ''  # to be filled later for verifications
ChangelogFrom = 'origin/staging'
ChangelogTo = 'origin/main'

All the variables are either create or overwrite to the existing variables list.

[FMTVariables]

This table houses all Formattable Variables Definition (e.g. {{- .Version -}}) specific to this packaging recipe. It shall appears onto all listed packages. Example:

1
2
3
[FMTVariables]
Lintian = '{{- .DataDir -}}/debian/lintian'
Profile = '{{- .DataDir -}}/debian/profiles'

All formatted variables are either create or overwrite to the existing variables list.

[[Dependencies]]

The [Dependencies] is an array of programs due for existence checking specifically meant for the entire packaging recipe. Therefore, it has extra square braces when defining its data.

It is compliant to Monteur’s internal Dependencies Checking function.

Here is an example for defining a list of dependencies:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
[[Dependencies]]
Name = 'DEB Builder'
Condition = 'all-all'
Type = 'command'
Command = 'debuild'

[[Dependencies]]
Name = 'GPG Tool'
Condition = 'all-all'
Type = 'command'
Command = 'gpg'

[[Dependencies]]
Name = 'Git for Changelog Generation'
Condition = 'all-all'
Type = 'command'
Command = 'git'

[Packages.XXX]

[Package] are the list of packages to be packaged by the [CMD] table. All these packages shall be iterated with the [CMD] table with the given variables above, including a now processed list of ChangelogEntries value (now a []string).

Depending on Metadata.Type, Monteur will execute a preparation executions before executing the [CMD] for a package. This reduces the need to build large [CMD] commands list and promotes consistency.

For Metadata.Type set to manual, to ensure you have complete control, this recipe type shall not execute the preparation sequences and all the packages are directly and completely controlled by [CMD].

The required fields are shown as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[Packages.001]
OS = [ 'linux' ]
Arch = [ 'amd64' ]
Name = '{{- .PkgName -}}-{{- .PkgVersion -}}-{{- .PkgOS -}}-{{- .PkgArch -}}'
Changelog = '{{- .DataDir -}}/changelog-{{- .PkgArch -}}'
Distribution = [
        'stable',
]
BuildSource = false

[Packages.001.Files]
'{{- .PackageDir -}}/monteur' = '{{- .BuildDir -}}/{{- .PkgOS -}}-{{- .PkgArch -}}'
'{{- .PackageDir -}}/License.pdf' = '{{- .LicensePath -}}'


[Packages.002]
OS = [ 'linux' ]
Arch = [ 'arm64' ]
Name = '{{- .App.ID -}}-{{- .App.Version -}}-{{- .PkgOS -}}-{{- .PkgArch -}}'
Changelog = '{{- .DataDir -}}/changelog-{{- .PkgArch -}}'
Distribution = [
        'stable',
]
BuildSource = false

[Packages.002.Files]
'{{- .PackageDir -}}/monteur' = '{{- .BuildDir -}}/{{- .PkgOS -}}-{{- .PkgArch -}}'
'{{- .PackageDir -}}/License.pdf' = '{{- .LicensePath -}}'

The fields' specifications are documented in the Package Meta section. For package API, you need the following fields (COMPULSORY):

[[CMD]]

[CMD] is basically the array of packaging commands or instructions for executing the packaging algorithms across each listed packages. Hence, this is why it has extra square braces.

Its values are complying to Monteur’s Commands Execution Units. Here is an example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
[CMD]]
Name = "Get GPG Secret Key for Verifications"
Type = 'command'
Condition = [ 'all-all' ]
Source = 'gpg --list-secret-keys "{{- .GPGID }}"'
Save = 'GPGExistence'

[[CMD]]
Name = "Verify GPG Secret Key Must Exists For Signing"
Type = 'is-not-empty'
Condition = [ 'all-all' ]
Source = '{{- .GPGExistence -}}'

[[CMD]]
Name = "Compile Deb Package"
Type = 'command'
Condition = [ 'all-all' ]
Location = '{{- .PackageDir -}}'
Source = 'debuild -b -k{{- .GPGID }} -a{{- index .PkgArch 0 }}'

...

Known Templates

Now that you understand how Monteur executes Package CI Job, fortunately, Monteur maintains a number of recipes for you to kick-start your deployment. Here are some currently maintained templates for different deployments: