Releasing Applications on a Release Branch

Releasing Applications on a Release Branch

This page covers the lifecycle and common scenarios for managing an application on a release branch after it has been created. For information on how release branches are created, see Creating a Release Branch.


Overview

Once a release branch exists, the CI system automatically manages module version updates through the update scheduler. Application maintainers are responsible for reviewing and approving the automated pull requests, monitoring descriptor validation results, and ensuring the application remains in a releasable state throughout the release cycle.


Replacing ^VERSION Placeholders

Immediately after release branch creation, all modules in application.template.json have "version": "^VERSION" placeholders. These are not valid version constraints — ^VERSION is an intentional placeholder set by the release preparation automation to signal that application maintainers must provide actual version constraints before the update scheduler can process the branch.

Why the placeholder exists: The release preparation workflow cannot determine the appropriate version constraint for each module across all applications. Each application maintainer must decide the correct version constraint based on the module versions relevant to their application.

What application maintainers must do:

  1. Check out the newly created release branch

  2. Edit application.template.json and replace every "version": "^VERSION" with a valid semver constraint — for example, "^2.0.0", "~2.1.0", ">=2.0.0", or "latest"

  3. Commit and push the changes to the release branch

Example — before (as created by release preparation):

{ "name": "mod-agreements", "version": "^VERSION", "preRelease": "false" }

Example — after (replaced by application maintainer using a caret constraint):

{ "name": "mod-agreements", "version": "^2.1.0", "preRelease": "false" }

Example — after (replaced by application maintainer using a tilde constraint):

{ "name": "mod-agreements", "version": "~2.1.0", "preRelease": "false" }

Any operator supported by the FOLIO module registry may be used (^, ~, >=, >, <=, <, =, latest). The choice depends on how broadly the application should track new module versions. See Version Constraints for the full operator reference.

What happens if placeholders are not replaced: The update scheduler validates template versions against a semver pattern before generating the application descriptor. ^VERSION does not match this pattern (it requires numeric digits after the ^ operator). When invalid versions are detected, the scheduler logs a warning and skips the application entirely — no descriptor is generated, no PR is created, and no updates occur until the placeholders are replaced with valid constraints.

Once all ^VERSION placeholders are replaced with valid version constraints, the update scheduler begins processing the branch on its next cycle (within 20 minutes). The first successful run generates the initial application descriptor and creates the first pull request.


Update Configuration on Release Branches

The update-config.yml entry for a new release branch is created automatically during release preparation. The default settings are:

Setting

Default Value

Description

Setting

Default Value

Description

enabled

true

Automated updates are active

need_pr

true

Changes require pull request approval

preRelease

"false"

Only stable release versions are considered

ruleset.enabled

true

Branch protection with required CI checks

In most cases, no manual changes to update-config.yml are required. Manual adjustments may be appropriate in the following scenarios:

  • Adjusting pr_reviewers — to add or change the team(s) that receive automated PR review requests

  • Adjusting labels — to change the labels applied to automated PRs (e.g., version-update). These labels help identify automated PRs in the repository's PR list

  • Temporarily disabling updates — setting enabled: false for the branch pauses the scheduler. This may be necessary during periods of active coordination (e.g., a module migration). Re-enable by setting enabled: true when ready

  • Configuring the Slack notification channel — set the SLACK_NOTIF_CHANNEL repository variable (in the application repository's Settings → Secrets and variables → Actions → Variables) to control which Slack channel receives post-merge notifications. This is a repository variable, not a setting in update-config.yml

For the complete configuration field reference, see Understanding Application Repository Files — .github/update-config.yml.


New Module Release Versions

When a module team publishes a new release version (e.g., mod-agreements 7.1.0), the following sequence occurs:

  1. The update scheduler detects that a newer version exists in the FOLIO module registry that satisfies the template constraint (e.g., ^7.0.0 matches 7.1.0)

  2. A pull request is created (or an existing PR is updated) showing the version change

  3. The PR body includes a summary of all module changes — added, upgraded, downgraded, or removed

  4. CI validation runs automatically on the PR

  5. Application maintainers review the changes and approve the PR

  6. The merge queue processes the PR automatically after approval

For the full PR-to-merge flow, see Managing Release Branch Updates.

Tagging and Manual Releases

After the update cycle completes (PR merged, descriptor published), application maintainers may choose to perform a manual release — tagging the current version and bumping the application minor version to prepare for the next iteration. For details on the manual release process, see Managing Release Branch Updates — Tag the Release Version.


Application Descriptor Verification

Two types of validation are performed on pull requests to a release branch. The overall validation result is: module interface integrity must pass, AND dependencies integrity must either pass or be skipped (see below).

Module Interface Integrity

This check verifies the internal consistency of the application descriptor. It runs on every PR.

  • Confirms that module interfaces are compatible — provided interfaces match the requirements of other modules in the application

  • Uses the FAR endpoint: POST /applications/validate

Common failure causes:

  • Two modules in the application declare conflicting interface versions

  • A required interface is not provided by any module in the application

  • The generated descriptor is structurally invalid

Note: Module version resolution happens at the descriptor generation stage (before validation). If a version constraint in application.template.json cannot be satisfied by any version in the FOLIO module registry, the folio-application-generator fails with a MODULE_NOT_FOUND error during generation — this is not a validation failure but a build failure.

Dependencies Integrity

This check validates the application's relationship with its declared dependencies. It does not run on every PR — it runs only when the platform descriptor is available or when rely_on_FAR is enabled. See Dependency Validation Behavior below.

  • Fetches dependency application descriptors from FAR (FOLIO Application Registry) or derives them from the platform descriptor in platform-lsp

  • Verifies that all declared dependencies have published descriptors with compatible versions

  • Ensures no missing or conflicting cross-application dependencies

  • Uses the FAR endpoint: POST /applications/validate-descriptors

Common failure causes:

  • A dependent application has not yet published its release descriptor to FAR

  • The dependency version constraint in the template does not match any published version

  • Cross-application interface requirements are not satisfied


Dependency Validation Behavior

The dependencies integrity check is conditional — it depends on the availability of the platform descriptor and the rely_on_FAR configuration setting.

Default behavior (rely_on_FAR not set or false):

  1. The validation action attempts to fetch the platform descriptor from platform-lsp for the current release branch

  2. If the platform descriptor exists — dependency descriptors are fetched from FAR based on the platform's application list, and full dependency validation is performed

  3. If the platform descriptor does not exist — the dependency validation step is skipped entirely. Only module interface integrity is evaluated. This is the normal state on newly created release branches before the platform descriptor has been published for that branch

When rely_on_FAR: true is configured:

  • The platform descriptor is not used at all

  • Dependency validation is performed directly against FAR — the validation action sends all application descriptors to the FAR /applications/validate-descriptors endpoint

  • This mode is useful when the platform descriptor is not the authoritative source for dependency resolution

Overall validation result:

The PR passes validation when: module interface integrity passes AND (dependencies integrity passes OR dependencies integrity was skipped).


Application Release Version Increment

Application versions follow specific increment rules depending on the phase:

Phase

Example

Logic

Phase

Example

Logic

Release preparation (branch creation)

1.0.02.0.0

Major version bump

First PR-based update

2.0.02.0.1

Patch increment — new update branch and PR created

Second PR-based update (after first merge)

2.0.12.0.2

Patch increment — update branch was deleted after merge, new cycle begins

While a PR is open and updated

2.0.2 (unchanged)

No increment — the update branch and PR already exist

The version is stored in pom.xml and serves as the source of truth. On release branches, the version does not include a -SNAPSHOT suffix.

How it works: The patch version increments each time a new update branch and pull request are created. This occurs at the start of each update cycle — when no update branch exists and no open PR exists for the release branch. Within a single PR's lifetime (while the update branch exists and the PR is open), subsequent scheduler runs push additional commits to the same branch without incrementing the version.

After a PR is merged, the post-merge flow deletes the update branch. On the next scheduler cycle, the absence of the update branch triggers a new patch increment, creating a fresh update branch and PR.


Update Branch Lifecycle

The CI system uses a dedicated update branch for managing automated PRs on each release branch. The lifecycle follows a create–use–delete–recreate pattern:

  1. Creation — the scheduler creates the branch (e.g., version-update/R1-2025) when new module versions are detected and no update branch exists

  2. PR association — a pull request is opened from the update branch to the release branch

  3. Ongoing updates — while the PR is open, subsequent scheduler runs push additional commits to the same update branch and update the PR description with the latest module changes

  4. Merge — after approval, the merge queue squash-merges the PR into the release branch

  5. Deletion — the post-merge flow automatically deletes the update branch via the GitHub API

  6. Recreation — on the next scheduler cycle, if new module version changes are detected, a new update branch is created, starting the cycle again

Orphan detection: If an update branch exists without a corresponding open PR, the system detects this condition and reports an error. The scheduler does not create a new PR in this case — the orphan branch must be deleted manually before the cycle can resume. This situation may occur if a PR was closed without merging or if a merge conflict left the branch in an inconsistent state.

Application maintainers should not create or modify update branches manually.


Merge Queue and Branch Rulesets

The merge queue behavior on release branches is governed by the branch ruleset. The branch ruleset is configured declaratively in update-config.yml and applied automatically by the CI system when the release branch is created or when the configuration changes.

The ruleset enforces:

  • Required CI checkeureka-ci / validate-application must pass before merging

  • Merge queue — uses the ALLGREEN grouping strategy and SQUASH merge method

  • Bypass — the Eureka CI GitHub Application is configured as a bypass actor, allowing automated post-merge operations

To verify the merge queue and ruleset configuration for a release branch, navigate to the application repository on GitHub → SettingsRules → locate the {branch}-eureka-ci ruleset (e.g., R1-2025-eureka-ci).

For full details on how rulesets are created, updated, and managed, see Branch Ruleset Automation.


When to Contact the CI Infrastructure Team

The following situations require coordination with the CI infrastructure team:

  • Release branch creation failed or needs to be re-created from scratch

  • Workflow files (.github/workflows/) require modification — these are centrally managed and cannot be changed in individual repositories

  • Branch ruleset issues that are not resolved by adjusting update-config.yml settings

  • Platform-wide coordination is needed for module moves or dependency changes that affect multiple applications simultaneously

  • The update scheduler is behaving unexpectedly (e.g., not running, creating duplicate PRs, or failing silently)


Related Pages