Skip to content

Pipeline Migration: bmo package push Flags#

This guide explains how to migrate CI/CD pipelines from the legacy sidecar .json approach to passing build metadata directly as flags on bmo package push.

Background#

The legacy deployment pipeline emitted a sibling <package>.json file alongside each zip artifact. This file contained build identity fields (Id, branch, commit hash, requester, etc.) that bmo package push consumed. The Orchestrator now owns the full deployment flow, making the sidecar a redundant artefact.

bmo package push now accepts all manifest fields as flags with automatic fallback:

Resolution order Source
1 Explicit CLI flag
2 Sibling .json sidecar (backward-compat baseline)
3 CI environment variables (auto-detected)
4 Local git (branch, commit, author)
5 Empty / generated ID

Migrating to flags is recommended. The sidecar continues to work if you cannot migrate immediately.


GitLab CI#

Before (sidecar)#

push-package:
  stage: publish
  script:
    - |
      # Legacy: emit sidecar JSON alongside the zip
      $meta = @{
        Version    = $env:CI_PIPELINE_IID
        Package    = "App_$($env:CI_PIPELINE_IID).zip"
        Id         = $env:CI_PIPELINE_ID
        Source_BranchName = $env:CI_COMMIT_REF_NAME
        Source_Version    = $env:CI_COMMIT_SHA
        Deployment_RequestedFor      = $env:GITLAB_USER_NAME
        Deployment_RequestedForEmail = $env:GITLAB_USER_EMAIL
        Build_DefinitionName         = $env:CI_JOB_NAME
        Sha256    = ""
        SizeBytes = 0
        Status    = "Uat"
      } | ConvertTo-Json
      $meta | Set-Content "App_$($env:CI_PIPELINE_IID).json"
    - bmo package push "App_$($env:CI_PIPELINE_IID).zip"

After (flags)#

push-package:
  stage: publish
  script:
    - |
      bmo package push "App_$($env:CI_PIPELINE_IID).zip" `
        --version  $env:CI_PIPELINE_IID `
        --id       $env:CI_PIPELINE_ID `
        --branch   $env:CI_COMMIT_REF_NAME `
        --commit   $env:CI_COMMIT_SHA `
        --requested-by       $env:GITLAB_USER_NAME `
        --requested-by-email $env:GITLAB_USER_EMAIL `
        --build-name         $env:CI_JOB_NAME

bmo auto-detects all GitLab CI environment variables (CI_PIPELINE_ID, CI_COMMIT_REF_NAME, CI_COMMIT_SHA, GITLAB_USER_NAME, GITLAB_USER_EMAIL, CI_JOB_NAME) when the pipeline sets them. You can therefore drop most flags and rely on auto-detection:

push-package:
  stage: publish
  script:
    # Auto-detection fills branch, commit, requester, build-name from CI env vars.
    # Only --version is required.
    - bmo package push "App_$($env:CI_PIPELINE_IID).zip" --version $env:CI_PIPELINE_IID

GitHub Actions#

GitHub Actions pipelines use different environment variables. bmo auto-detects them from GITHUB_* variables.

jobs:
  publish:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4

      - name: Push package
        run: |
          bmo package push "App_${{ github.run_number }}.zip" `
            --version ${{ github.run_number }}
        # Auto-detected from GitHub Actions env vars:
        #   --branch   : GITHUB_HEAD_REF (PR) or GITHUB_REF_NAME (branch push)
        #   --commit   : GITHUB_SHA
        #   --id       : GITHUB_RUN_ID
        #   --build-name : GITHUB_WORKFLOW
        #   --requested-by : GITHUB_ACTOR
        # Note: --requested-by-email is not available in GitHub Actions; left empty.

If you need the email field populated, pass it explicitly via a secret:

      - name: Push package
        env:
          DEPLOYER_EMAIL: ${{ secrets.DEPLOYER_EMAIL }}
        run: |
          bmo package push "App_${{ github.run_number }}.zip" `
            --version            ${{ github.run_number }} `
            --requested-by-email $env:DEPLOYER_EMAIL

Azure DevOps#

bmo auto-detects BUILD_BUILDID, BUILD_DEFINITIONNAME, BUILD_SOURCEBRANCHNAME, BUILD_SOURCEVERSION, BUILD_REQUESTEDFOR, and BUILD_REQUESTEDFOREMAIL.

- task: PowerShell@2
  displayName: Push package
  inputs:
    targetType: inline
    script: |
      bmo package push "App_$(Build.BuildNumber).zip" --version $(Build.BuildNumber)
      # All other fields are auto-detected from BUILD_* variables.

IIS Pool Naming Strategy#

After migrating, configure the PoolNamingStrategy in each Agent's appsettings.json to specify how pool names are derived from the package version. The Orchestrator no longer controls this — it is fully Agent-local.

{
  "Agent": {
    "Environments": {
      "Acceptatie": {
        "BasePath": "F:\\Acceptatie",
        "NamingStrategy": "PerEnvironment"
      },
      "Productie": {
        "BasePath": "F:\\Productie",
        "NamingStrategy": "PerMajorMinor"
      }
    }
  }
}
Strategy Pool name example Use case
PerEnvironment Acceptatie Single shared pool; zero downtime between versions
PerMajor Productie_25 One pool per major release train
PerMajorMinor Productie_25.5 One pool per sprint cycle (default)
PerVersion Productie_25.5.32 Fully isolated; simplest rollback, highest pool count

The optional AppPoolPrefix key overrides the environment name as the pool prefix:

"Productie": {
  "NamingStrategy": "PerMajorMinor",
  "AppPoolPrefix": "Prod"
}

This yields Prod_25.5 instead of Productie_25.5.

When no NamingStrategy is configured for an environment, the Agent falls back to the FormattedAppVersion value that the Orchestrator computed and included in the deployment payload. This ensures all existing deployments keep working while you migrate Agent configs one environment at a time.


Migration Checklist#

  • [ ] Update pipeline scripts to pass --version (required) and any fields not auto-detected
  • [ ] Remove sidecar JSON generation step from the pipeline
  • [ ] Remove any artifact publishing of the .json file
  • [ ] Add NamingStrategy to each environment block in the Agent's appsettings.json
  • [ ] Verify a round-trip: push a package, then bmo package show <version> and confirm all fields are populated correctly