Skip to main content

Build status

Every microfrontend is built by the CI of the provider its repository lives on. Without a place that collects those runs, checking whether the last pipeline passed means one browser tab per repository.

The Builds page is that place: one row per microfrontend, the outcome of its latest run, the recent history behind it, and the version each environment is currently serving.

The Builds page with a status badge per microfrontend and one row expanded on its last runs

:::info Nothing is stored The runs are read from the providers when you open the page, and re-read while you keep it open. MFE Orchestrator keeps no build history of its own, so the page shows what the providers show and nothing more. :::

Reading the table

One row per microfrontend of the current project, sorted by name:

ColumnContent
MicrofrontendName and slug
Last buildStatus badge of the most recent run, or why no run could be read
Tag / branchThe ref that run was started from, tags included
Last built versionThe most recent version whose bundle actually reached the platform
One column per environmentThe version that environment serves, taken from its active deployment

The environment columns come after the fixed ones, in the order the environments are configured on the project, and the production one is flagged with a badge.

Three version columns sound redundant until an incident makes the difference matter:

  • Last built version is the newest bundle uploaded to the platform.
  • The environment columns are what a deployment froze. A deployment ships a fixed set of versions, so an environment keeps serving what it was given even after a newer bundle exists.
  • Expand a row and a third one appears, the selected version: what the microfrontend currently points at, which is what the next deployment would pick up.

A newer last built version than the one in the production column is not a fault — it is the gap between "built" and "deployed", and this page is where you see it.

Expanding a row also shows the repository the microfrontend is linked to and the last five runs of that repository, newest first, each with its status, ref, workflow name, start moment, who started it, and a link to the run on the provider. Who started it never appears on GitLab: the pipelines list endpoint does not carry it, so the field is left unset and the run is shown without it.

Status badges

Each provider describes a run in its own vocabulary; the console reduces all of them to six buckets.

StatusMeaning
QUEUEDAccepted but not started — including a GitLab pipeline waiting on a manual action
RUNNINGIn progress
SUCCESSFinished and passed (Azure partiallySucceeded counts as passed)
FAILEDFinished and failed, timed out, or failed to start
CANCELEDCanceled or skipped — and a GitHub run whose conclusion is neutral
UNKNOWNThe provider reported a state this platform does not know

A run still in progress is RUNNING, whatever result the provider left on it from a previous attempt: GitHub and Azure DevOps both split the outcome over two fields, and the second one only means something once the first says the run is over.

Cancellation is the exception, on both providers that report it as a state of its own. Azure DevOps cancelling and GitLab canceling are runs that have not finished yet, and both are shown as CANCELED rather than RUNNING, because the outcome is already decided.

When a row has no runs

A microfrontend without runs says why, instead of showing an empty history:

ReasonCause
NO_REPOSITORYNo code repository is connected to the microfrontend, or the connection is disabled
REPOSITORY_NOT_FOUNDIt points at a code repository connection that no longer exists
PROVIDER_ERRORThe provider call failed — revoked token, network error, missing Azure configuration

PROVIDER_ERROR is confined to the row that produced it: one unreachable provider never blanks the page, and the row keeps its versions. A microfrontend whose repository is reachable but has never run a pipeline carries no reason at all and an empty run list.

Where the runs come from

The runs are read through the code repository connection the microfrontend points at, with the token stored on that connection:

ProviderAddressed byRead from
GitHubThe repository name, under the organization or user of the connectionGET /repos/:owner/:repo/actions/runs
GitLabThe repository idGET /projects/:id/pipelines
Azure DevOpsThe repository id, inside the organization and project of the connectionGET /_apis/build/builds?repositoryId=…&repositoryType=TfsGit

Runs are read repository-wide: every workflow, pipeline or build definition attached to the repository is in scope, and there is no way to select "the build pipeline" among them.

Live updates

The page opens a Server-Sent Events stream and keeps it for as long as it stays open. The header shows whether the stream is connected and the moment of the last snapshot received.

Two things are worth knowing about what "live" means here:

  • The server re-reads the providers every 15 seconds and only sends a frame when something actually changed. No provider webhook is involved, so a run that starts is visible within 15 seconds, not instantly.
  • A snapshot is reused for 15 seconds and shared by everyone watching the same project, so Refresh inside that window returns the cached snapshot rather than hammering the provider. The last update moment is when the snapshot was read, which is how you tell a fresh one from a reused one.

A provider failure during a poll ends that round, not the connection: the last snapshot stays on screen and the next poll retries.

API

Both endpoints are authenticated and scoped to the project carried by the Project-Id header.

MethodPathDescription
GET/api/buildsCurrent build status of the project, as one snapshot
GET/api/builds/streamThe same snapshot, pushed over SSE as it changes

Neither takes a query parameter or a body. The snapshot carries the environments of the project, and for each microfrontend its selectedVersion, latestBuiltVersion, a versionByEnvironmentId map and up to five builds; a microfrontend that could not be read carries unavailableReason and an empty builds.

:::note EventSource cannot be used The API requires an Authorization and a Project-Id header on every call — the console sends an issuer header alongside them, naming the identity provider the token came from — and EventSource cannot send any of them. Consume the stream with fetch, as the console does. :::

Limits worth knowing

  • Only the last five runs per microfrontend are read, and only for the repository as a whole.
  • On Azure DevOps only builds of Azure Repos Git repositories are matched; a pipeline defined on a repository hosted elsewhere is not listed.
  • Nothing is persisted: no trend, no duration, no failure rate.
  • The status is at most 15 seconds old.
  • A token without access to the CI of a repository yields PROVIDER_ERROR even when the repository itself is readable.

Where to go next