This action sets up the Metanorma toolchain and adds the command-line tools to the PATH. Metanorma is a suite of tools for authoring standards documents, supporting ISO, IEC, IEEE, IETF, ITU, and other standards organizations.
- Extra flavors support: Install additional metanorma flavor gems (both public and private) in a single step - consolidates functionality from the separate
setup-flavorsaction - Private flavor support: Built-in GitHub Packages authentication for private flavors (bsi, nist, plateau) via
github-packages-tokeninput - Idempotent installation: Automatically skips redundant installations when Metanorma is already installed with the same configuration - saves time in workflows that may call the action multiple times
- YAML-based version registry: Fetches version data directly from metanorma/versions repository YAML files - no Ruby/Bundler dependencies
- Pre-built Gemfile.lock integration: Automatically uses pre-tested Gemfile.lock files from metanorma/versions for deterministic, tested dependency resolution
- Dependency updates while keeping metanorma-cli pinned: New
bundle-updateinput allows updating dependencies while preserving the metanorma-cli version - Revision-based Snap installation: Install specific Metanorma versions on Linux using Snap revision pinning
- Platform-specific version management: Each platform (Chocolatey, Homebrew, Snap, Gem) tracks available versions separately
- Fontist formula updates: Optional automatic fontist formula updates after gem installation
- Multi-method installation: Support for native package managers, gem-based installation, or auto-detection
- uses: actions-mn/setup@v3
with:
# Version of metanorma-cli gem to install
# For gem installations: empty (default) respects Gemfile.lock, "latest" runs bundle update, or specific version like "1.7.1" pins that version
version: '' # optional, default is ''
# Snapcraft channel (Linux only): stable, candidate, beta, edge
# Only used when installation-method is 'native' on Linux
snap-channel: 'stable' # optional, default is 'stable'
# Allow pre-release versions for Chocolatey packages (Windows only)
choco-prerelease: '' # optional
# Installation method: 'auto' (default), 'native', 'gem'
# auto: Auto-detect based on environment
# native: Force native package manager (brew/snap/choco)
# gem: Install via bundle (requires Ruby setup first)
installation-method: 'auto' # optional, default is 'auto'
# Path to custom Gemfile for gem-based installation
gemfile: '' # optional
# Bundler version for gem-based installation
bundler-version: '2.6.5' # optional, default is '2.6.5'
# Update fontist formulas after gem installation
# Only applies to gem-based installations
fontist-update: 'true' # optional, default is 'true'
# Update dependencies while keeping metanorma-cli version pinned
# Only applies to gem-based installations
# When true, runs 'bundle update --except metanorma-cli'
bundle-update: 'false' # optional, default is 'false'
# Use pre-tested Gemfile.lock files from metanorma/versions repository
# When true and a specific version is requested, uses pre-built lock files
# When false, respects existing Gemfile.lock in workspace
use-prebuilt-locks: 'true' # optional, default is 'true'
# Space-separated list of extra flavor gems to install
# Public flavors: iso, ietf, ribose, cc, plateau, etc. (from RubyGems)
# Private flavors: bsi, nist (require github-packages-token)
extra-flavors: '' # optional, default is ''
# GitHub token to access private packages at rubygems.pkg.github.com/metanorma
# Required for private flavors: bsi, nist
github-packages-token: '' # optional, default is ''| Output | Description |
|---|---|
version |
The installed Metanorma version |
platform |
The platform Metanorma was installed on |
installation-method |
The installation method used |
idempotent |
Whether the action detected an existing installation (true) or performed a new installation (false) |
The action automatically detects the appropriate installation method based on the platform:
- Windows: Uses Chocolatey
- macOS: Uses Homebrew
- Linux: Uses Snap
- Docker: Uses gem-based installation
- uses: actions-mn/setup@v3Forces installation using the platform's native package manager:
- uses: actions-mn/setup@v3
with:
installation-method: 'native'
version: '1.14.4'Different platforms have different version availability. See the Platform Version Matrix for details.
Windows (Chocolatey)
- Latest:
1.14.4 - Version data fetched from:
metanorma/versionsrepository (data/chocolatey/versions.yaml)
macOS (Homebrew)
- Latest:
1.13.0 - Version data fetched from:
metanorma/versionsrepository (data/homebrew/versions.yaml)
Linux (Snap)
- Latest:
1.14.4 - Uses revision pinning for version-specific installation
- Revision data fetched from:
metanorma/versionsrepository (data/snap/versions.yaml)
Docker Containers (for gem-based installation)
- Gemfile availability tracked in:
metanorma/versionsrepository (data/gemfile/versions.yaml)
Install Metanorma as a Ruby gem using Bundler. Requires Ruby to be set up first.
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
bundler-cache: true
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'Install the latest version available on your platform:
- uses: actions-mn/setup@v3Install a specific Metanorma version using the native package manager:
- uses: actions-mn/setup@v3
with:
version: '1.14.4'Note: Version availability varies by platform. See Platform Version Matrix.
Install a specific Metanorma version using gem:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'
version: '1.14.0'When using gem-based installation with an existing Gemfile, the action respects the version specified in Gemfile.lock:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'The action will:
- Detect if a Gemfile exists in your workspace
- Respect the versions specified in Gemfile.lock
- Not modify your Gemfile if it exists
When you specify a version, the action automatically uses pre-tested Gemfile.lock files from the metanorma/versions repository for deterministic, tested dependency resolution:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'
version: '1.14.3'This provides:
- Deterministic installations: All dependencies are pinned to tested versions
- Faster installation: No need to run
bundle installwith dependency resolution - Tested compatibility: Each Gemfile.lock is pre-tested with the corresponding metanorma-cli version
Gemfile.lock Replacement Warning: If your workspace has an existing Gemfile.lock with a different metanorma-cli version, the action will replace it with the pre-built lock file and display a prominent warning:
┌──────────────────────────────────────────────────────────────────┐
│ ⚠️ GEMFILE.LOCK REPLACED WITH PRE-BUILT VERSION │
├──────────────────────────────────────────────────────────────────┤
│ Your Gemfile.lock has been replaced with a pre-tested lock file │
│ from metanorma/versions repository. │
│ │
│ To disable this behavior, use use-prebuilt-locks: false │
└──────────────────────────────────────────────────────────────────┘
To disable automatic Gemfile.lock replacement and respect your workspace's Gemfile.lock:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'
version: '1.14.3'
use-prebuilt-locks: 'false'To update all gem dependencies while keeping the metanorma-cli version pinned:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'
version: '1.14.3'
bundle-update: 'true'This runs bundle update --except metanorma-cli, which:
- Updates all gems except metanorma-cli to their latest compatible versions
- Preserves the specified metanorma-cli version (1.14.3 in this example)
- Ensures you get security updates and bug fixes from dependencies
To update Metanorma to the latest gem version:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'
version: 'latest'This runs bundle update metanorma-cli to get the latest version.
Specify a custom Gemfile path:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'
gemfile: 'tools/Gemfile'By default, gem-based installation runs bundle exec fontist update to download the latest font formulas. To disable:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'
fontist-update: 'false'Install Metanorma from a specific Snap channel:
- uses: actions-mn/setup@v3
with:
installation-method: 'native'
snap-channel: 'edge' # options: stable, candidate, beta, edgeOn Linux, you can install a specific Snap revision corresponding to a Metanorma version:
- uses: actions-mn/setup@v3
with:
installation-method: 'native'
version: '1.13.9'The action will:
- Detect the runner's architecture (amd64 or arm64)
- Look up the Snap revision for version 1.13.9 and the detected architecture from
platform-snap-native-versions.json - Install using
snap install metanorma --revision=<N> --classic - Hold the revision to prevent automatic updates
This ensures you get exactly the Metanorma version you requested, with the ability to pin that specific Snap revision.
Architecture Support: Snap revision pinning supports both amd64 and arm64 architectures. The revision data includes architecture-specific revision numbers, and the action automatically selects the correct revision based on the runner's architecture.
To install pre-release versions from Chocolatey:
- uses: actions-mn/setup@v3
with:
installation-method: 'native'
choco-prerelease: 'true'The action can install additional metanorma flavor gems beyond the default CLI installation. This replaces the separate actions-mn/setup-flavors action.
Public flavors are available on RubyGems and don't require authentication:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
- uses: actions-mn/setup@v1
with:
installation-method: 'gem'
extra-flavors: 'iso ietf ribose'Private flavors (bsi, nist) are hosted on GitHub Packages and require authentication:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
- uses: actions-mn/setup@v1
with:
installation-method: 'gem'
extra-flavors: 'bsi nist'
github-packages-token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}| Flavor | Description | Requires Token |
|---|---|---|
bsi |
British Standards Institution | Yes |
nist |
National Institute of Standards and Technology | Yes |
iso |
International Organization for Standardization | No |
ietf |
Internet Engineering Task Force | No |
ribose |
Ribose flavor | No |
cc |
CalConnect (formerly csd) | No |
plateau |
Plateau flavor | No |
You can install both public and private flavors together:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
- uses: actions-mn/setup@v1
with:
installation-method: 'gem'
extra-flavors: 'iso bsi ribose'
github-packages-token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}When installing the BSI flavor, the action automatically configures fontist private formulas for proprietary fonts. This requires the github-packages-token to access the private fontist formulas repository.
If you were previously using the separate setup-flavors action:
Before:
- uses: actions-mn/setup@v3
- uses: actions-mn/setup-flavors@v1
with:
extra-flavors: bsi
github-packages-token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}After:
- uses: actions-mn/setup@v3
with:
installation-method: gem
extra-flavors: bsi
github-packages-token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}The action automatically detects when Metanorma is already installed with the same configuration and skips redundant installation steps. This is useful in workflows where the action may be called multiple times.
When the action runs, it:
- Checks if a previous installation state file exists (
.metanorma-setup-state.json) - Compares the current configuration (version, platform, installation method) with the saved state
- If the configuration matches and Metanorma is available in PATH, skips the installation
- If the configuration has changed or Metanorma is not available, performs a fresh installation
The idempotent output indicates whether installation was skipped:
- uses: actions-mn/setup@v3
id: setup-metanorma
- name: Check if installation was skipped
run: |
if [ "${{ steps.setup-metanorma.outputs.idempotent }}" == "true" ]; then
echo "Metanorma was already installed, skipped redundant installation"
else
echo "Metanorma was freshly installed"
fiThe action reinstalls Metanorma if any of these configuration values change:
versioninstallation-methodsnap-channel(Linux)choco-prerelease(Windows)platform(detected automatically)
For gem-based installation in Docker:
jobs:
test:
runs-on: ubuntu-latest
container:
image: ruby:alpine
steps:
- uses: actions/checkout@v4
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'
- run: bundle exec metanorma --versionFor Alpine-based containers with native Ruby:
jobs:
test:
runs-on: ubuntu-latest
container:
image: ruby:alpine
steps:
- uses: actions/checkout@v4
# Alpine's musl libc is incompatible with ruby/setup-ruby
# Use gem installation directly
- uses: actions-mn/setup@v3
with:
installation-method: 'gem'
- run: bundle exec metanorma --versionThe action includes comprehensive integration tests that verify both native and gem-based installation methods across all platforms (Ubuntu, macOS, Windows). These tests:
- Single Document Compilation: Compiles a sample Metanorma document to verify the installation works correctly
- Site Generation: Runs
metanorma site generateon a sample repository to test full workflow functionality
The integration tests use the mn-samples-cc repository for testing, which provides a small, fast-compiling sample document set.
Test Matrix:
| Platform | Native Method | Gem Method |
|---|---|---|
| Ubuntu (Snap) | ✅ Tested | ✅ Tested |
| macOS (Homebrew) | ✅ Tested | ✅ Tested |
| Windows (Chocolatey) | ✅ Tested | ✅ Tested |
| Version | Windows (Chocolatey) | macOS (Homebrew) | Linux (Snap) | Gem (RubyGems) |
|---|---|---|---|---|
| 1.14.4 | ✅ | ❌ | ✅ (rev 288) | ✅ |
| 1.14.3 | ✅ | ❌ | ✅ (rev 287) | ✅ |
| 1.13.9 | ✅ | ❌ | ✅ (rev 276) | ✅ |
| 1.13.8 | ✅ | ❌ | ✅ (rev 268) | ✅ |
| 1.13.7 | ✅ | ❌ | ✅ (rev 263) | ✅ |
| 1.13.6 | ✅ | ❌ | ✅ (rev 256) | ✅ |
| 1.13.4 | ✅ | ❌ | ✅ (rev 244) | ✅ |
| 1.13.2 | ✅ | ❌ | ✅ (rev 232) | ✅ |
| 1.13.0 | ❌ | ✅ | ✅ (rev ~220) | ✅ |
| 1.11.5 | ✅ | ❌ | ✅ (rev 210) | ✅ |
| 1.11.4 | ✅ | ❌ | ✅ (rev 204) | ✅ |
| 1.11.3 | ✅ | ❌ | ✅ (rev 198) | ✅ |
| 1.11.0 | ✅ | ❌ | ✅ (rev 190) | ✅ |
Legend:
- ✅ Available
- ❌ Not available
- Snap revision numbers shown are for amd64 (arm64 revisions also tracked)
The action fetches version data from the metanorma/versions repository using YAML files:
- Snap:
data/snap/versions.yaml- Revision mapping for version-specific installation - Gemfile:
data/gemfile/versions.yaml- Available gem versions with Gemfile availability - Homebrew:
data/homebrew/versions.yaml- Tap versions with tag/commit information - Chocolatey:
data/chocolatey/versions.yaml- Package versions with pre-release flags
Version fetching is done via HTTPS using pure TypeScript/Node.js - no Ruby, Bundler, or git clone required. The YAML files are fetched directly from GitHub's raw content URLs and parsed using the js-yaml library.
Fallback behavior: If version data cannot be fetched (e.g., network issues), the action gracefully falls back to existing behavior for native installations.
Snap packages don't support version-specific channels like 1.14.3/stable. Instead, each upload to the Snap Store gets a unique revision number. To install a specific Metanorma version via Snap:
- The action fetches version data from the
metanorma/versionsrepository (data/snap/versions.yaml) - Finds the corresponding Snap revision for that version and architecture
- Installs using
snap install metanorma --revision=<N> --classic - Holds the revision with
snap refresh metanorma --hold
Example:
- uses: actions-mn/setup@v3
with:
version: '1.13.9'This installs Snap revision 276 (which corresponds to Metanorma 1.13.9 on amd64) or revision 277 (for arm64) and holds it at that revision.
Revision Data Format:
The YAML file contains version entries with architecture-specific revision data:
versions:
- version: "1.13.9"
revision: 276
channel: stable
arch: amd64
published_at: "2024-01-15T10:30:00Z"
- version: "1.13.9"
revision: 277
channel: stable
arch: arm64
published_at: "2024-01-15T10:30:00Z"- Yes,
node_modulesneeds to be committed - During development
node_modulesmay be modified butdevDependenciesshould not be committed, be careful
The scripts and documentation in this project are released under the MIT License