Working with Application Repositories

Working with Application Repositories

This guide is for teams who own or contribute to app-* repositories in the FOLIO Eureka CI system. It provides practical guidance on day-to-day tasks — from creating a new application repository to managing release branches. For architectural details about how the CI/CD system is implemented, see the sibling pages: CI flow [snapshot], Release preparation, CI flow [release].


How-To Guides

  1. Create a New Application Repository — Set up a new app-* repository from scratch with all required files and CI configuration.

  2. Create Application Release Branch — Step-by-step instructions for triggering platform-wide or single-application release preparation workflows.

  3. Release Application Updates — The automated PR flow from module version detection through CI validation, approval, merge queue processing, and post-merge publishing.

  4. Adding, Removing, or Moving Modules — Modify the application's module composition, including splitting applications.

Reference Guides

  1. Understanding Application Repository Files - Field-by-field reference for every file in an app-* repository.

  2. Creating a Release Branch — What happens during release branch creation, two modes of operation, automation steps, and post-creation checklist.

  1. Releasing Applications on a Release Branch — Managing the application lifecycle on a release branch: version resolution, validation, dependency handling, and version increments

  2. Branch Ruleset Automation — How branch rulesets are automatically created and managed for release branches, including merge queue and bypass actor configuration.

  3. Eureka CI GitHub Application — The serverless event router that bridges GitHub webhook events to GitHub Actions workflows for CI validation, post-merge processing, and ruleset automation.

  4. Application and Platform Update Flows — End-to-end architecture of the two-level CI update pipeline: how application-level updates (every 20 min) and platform-level updates (hourly) work together, including validation checkpoints.


What is an Application Repository?

Each app-* repository defines a FOLIO application — a composition of backend modules (mod-*) and frontend modules (folio_*) and their descriptors. The Eureka CI system automatically resolves module versions, validates module interfaces, and publishes application descriptors to the FOLIO Artifact Registry (FAR).

Applications can depend on other applications (e.g., app-agreements depend on app-licenses). The CI system validates these dependency chains automatically.


Repository File Layout

Every app-* repository follows the same structure:

app-{name}/ ├── pom.xml — Version source of truth, Maven build config ├── application.template.json — Module composition template (ACTIVE) ├── app-{name}.template.json — Legacy template (LEFT FOR BACKWARD COMPATABILITY) ├── application.lock.json — Auto-generated state file (resolved versions) └── .github/ ├── update-config.yml — CI update & branch configuration └── workflows/ ├── update-scheduler.yml — Runs every 20 min (read-only) └── release-preparation.yml — Manual release trigger (read-only)

Important: application.template.json is the authoritative template file — it is referenced in pom.xml via <templatePath>. The app-{name}.template.json file is a legacy artifact and left for backward compatibility.


Update Configuration Layout

The .github/update-config.yml file controls all automated update behavior. Here is the annotated structure:

# .github/update-config.yml update_config: enabled: true # Enable/disable automated updates update_branch_format: version-update/{0} # PR branch naming ({0} = target branch) labels: # Labels applied to automated PRs - version-update pr_reviewers: # GitHub teams/users for PR review - folio-org/kitfox - folio-org/{your-team} ruleset: # Branch protection ruleset config enabled: true pattern: "{0}-eureka-ci" # Ruleset name ({0} = branch name) required_checks: - context: "eureka-ci / validate-application" merge_queue: # Merge queue settings enabled: true check_response_timeout_minutes: 60 grouping_strategy: "ALLGREEN" max_entries_to_build: 5 max_entries_to_merge: 5 merge_method: "SQUASH" min_entries_to_merge: 1 min_entries_to_merge_wait_minutes: 5 bypass_actors: - actor_type: "Integration" bypass_mode: "always" branches: # Per-branch update settings - snapshot: # Branch name enabled: true need_pr: false # Direct commits (no PR) pre_release: "only" # Only pre-release versions descriptor_build_offset: "100200000000000" ruleset: enabled: false - R1-2025: # Release branch example enabled: true need_pr: true # Updates via PR preRelease: "false" # Stable versions only

Each branch entry controls how updates are applied to that branch independently. The need_pr field determines whether the scheduler commits directly or creates a pull request. See Understanding Application Repository Files for the complete field reference.


Template Layout

The application.template.json file defines the module composition. Maven variables (${project.name}, ${project.version}, ${project.description}) are resolved during build from pom.xml.

Pre-release branch example (app-acquisitions, snapshot):

{ "name": "${project.name}", // From pom.xml <name> "version": "${project.version}", // From pom.xml <version> "description": "${project.description}", // From pom.xml <description> "dependencies": [ { "name": "app-platform-complete", // Required application dependency "version": "^3.0.0-SNAPSHOT", // Constraint with -SNAPSHOT suffix "preRelease": "only" // Match pre-release dependencies only } ], "modules": [ { "name": "mod-organizations", // Backend module name "version": "latest", // Any available version "preRelease": "only" // Pre-release builds only } ], "uiModules": [ { "name": "folio_organizations", // Frontend module name "version": "latest", "preRelease": "only" } ] }

Release branch example (app-acquisitions, R1-2025):

{ "name": "${project.name}", "version": "${project.version}", "description": "${project.description}", "dependencies": [ { "name": "app-platform-complete", "version": "^3.0.0", // Caret range, stable only "preRelease": "false" } ], "modules": [ { "name": "mod-organizations", "version": "^1.0.0", // Caret range constraint "preRelease": "false" // Release versions only } ], "uiModules": [ { "name": "folio_organizations", "version": "^6.0.0", "preRelease": "false" } ] }

Each module entry uses a version constraint and a preRelease filter to control which module versions the CI system resolves. The two most common patterns:

  • Pre-release branch: "version": "latest" + "preRelease": "only" — resolves the newest pre-release build

  • Release branch: "version": "^X.Y.Z" + "preRelease": "false" — resolves the newest stable release within the caret range

For the full operator table (latest, ^, ~, >=, >, <=, <, =), preRelease value reference, and -SNAPSHOT suffix usage, see the Version Constraints section in the Understanding Application Repository Files.


State File Layout

The application.lock.json is auto-generated by the CI system. It contains the fully resolved application descriptor with resolved module versions and complete module descriptors. Never edit this file manually.

Pre-release branch example (app-agreements, snapshot):

{ "id": "app-agreements-1.0.0-SNAPSHOT.100200000005244", // Resolved application ID "name": "app-agreements", "version": "1.0.0-SNAPSHOT.100200000005244", // Resolved version with build offset "description": "Application descriptor for ...", "modules": [ { "id": "mod-agreements-7.3.0-SNAPSHOT.832", // Resolved module ID "name": "mod-agreements", "version": "7.3.0-SNAPSHOT.832" // Pinned pre-release version } ], "uiModules": [ { "id": "folio_agreements-12.1.1099000000001757", "name": "folio_agreements", "version": "12.1.1099000000001757" } ], "dependencies": [ { "name": "app-licenses", "version": "^1.0.0-SNAPSHOT", "preRelease": "only" } ], "moduleDescriptors": [ ... ], // Full backend module descriptors "uiModuleDescriptors": [ ... ] // Full frontend module descriptors }

Release branch example (app-acquisitions, R1-2025):

{ "id": "app-acquisitions-2.0.2", // Clean release ID "name": "app-acquisitions", "version": "2.0.2", // Resolved release version "modules": [ { "id": "mod-organizations-1.9.2", "name": "mod-organizations", "version": "1.9.2" // Pinned release version } ], "uiModules": [ { "id": "folio_organizations-6.0.1", "name": "folio_organizations", "version": "6.0.1" } ], "dependencies": [ { "name": "app-platform-complete", "version": "^3.0.0", "preRelease": "false" } ], "moduleDescriptors": [ ... ], "uiModuleDescriptors": [ ... ] }

The state file holds the latest version of the application descriptor — the same descriptor that is published to FAR. The folio-application-generator uses it as the baseline to produce an updated descriptor and determine whether any module versions have changed. For the complete field reference, see the state file reference.


Key Concepts

  • Application template (application.template.json) — Defines what modules and what versions belong to the application. This is the file that teams edit to add, remove application module composition or change the module version constraints.

  • State/lock file (application.lock.json) — Auto-generated file containing the latest version of the application descriptor — the same descriptor that is published to FAR. The folio-application-generator uses it as the baseline to produce an updated descriptor and determine whether any module versions have changed. Never edit it manually.

  • Version constraints — Each module entry in the template specifies a version constraint and a preRelease filter. The CI system resolves these constraints against the FOLIO module registry to find matching versions. See the Template Layout section above for common patterns and a link to the full operator reference.

  • Configuration file (.github/update-config.yml) — Controls the automated update behavior for the repository: which branches are tracked, whether updates require PRs or are committed directly (need_pr), which pre-release policy applies per branch (pre_release), PR reviewers and labels, and branch ruleset/merge queue settings. See Understanding Application Repository Files for the full field reference.

  • Branch ruleset — GitHub branch protection with required CI checks (eureka-ci / validate-application) and merge queue. Configured declaratively via update-config.yml and applied automatically by the CI system.

  • Update strategy — The update scheduler runs every 20 minutes for each branch configured in update-config.yml. Whether updates are committed directly or via pull request is controlled by the need_pr setting per branch — not by branch type. Typically, branches tracking pre-release versions use direct commits (need_pr: false), while branches tracking release versions use PRs for team review (need_pr: true), but this is fully configurable.


Slack Notifications

The CI system sends Slack notifications at key points in the release workflow — for example, after a version-update PR is merged and the application descriptor is published. The notification channel is controlled by the SLACK_NOTIF_CHANNEL repository variable.

Setting up notifications:

  1. Navigate to the application repository on GitHub → SettingsSecrets and variablesActionsVariables

  2. Create or update the SLACK_NOTIF_CHANNEL variable with the target Slack channel ID

Where notifications are sent:

  • Team channel — the channel specified by SLACK_NOTIF_CHANNEL in the application repository. Each application repository can have its own channel

  • General channel — an organization-wide channel configured at the CI infrastructure level (GENERAL_SLACK_NOTIF_CHANNEL). This is not configurable per repository

If SLACK_NOTIF_CHANNEL is not set, only the general channel receives notifications. If the variable is set but the channel ID is incorrect, notifications silently fail. To troubleshoot notification issues, verify the variable value and request assistance in the #folio-rancher-support Slack channel if needed.