People who use your software need to see which version they run. Coroid gives every release a version and a build number, passes both to the pipeline that builds it, and checks afterwards that the environment runs the release you deployed.
1. Coroid names it
Release
1.4.1
Build 12
From Coroid, a file in your repository, or your pipeline.
2. Your pipeline builds it
Your CI/CD
COROID_VERSION=1.4.1
COROID_BUILD_NUMBER=12
COROID_COMMIT_SHA=3da015d…
The values arrive as variables or workflow inputs.
3. People see it
About
Version 1.4.1 (12)
Shown in the app and written to release.json.
4. Coroid confirms it
GET /version.json
Verified
Pipeline reported 1.4.1, build 12
After a deployment, Coroid reads the version URL.
Everything on this page is set per project in Releases → Release settings → Versioning.
Where the version comes from
Choose one source per project:
- Coroid assigns it (the default): Coroid suggests the next version when
you prepare a release. It raises the last number of the highest version the
project has released, so
1.4.0is followed by1.4.1. The first release is0.1.0. Type a different version whenever you need one. - Read it from the repository: Coroid reads the version your code
declares at the release commit. It looks in
VERSION,package.json,app.json(Expo),pubspec.yaml, the Android Gradle file,Cargo.toml,pyproject.tomland the Xcode project, or only in the file you name. If the file still has a version an earlier release used, Coroid asks you to raise it first. - My pipeline assigns it: your CI/CD picks the version, for example with semantic-release or from a tag, and reports it with the deployment.
Every release also gets a build number. Build numbers only go up and are never
reused within a project, which is what app stores require from iOS
CFBundleVersion and Android versionCode.
What the build receives
When Coroid starts a GitHub Actions workflow or a GitLab CI/CD pipeline for a release, it passes these values:
| GitLab variable | GitHub input | Value |
|---|---|---|
COROID_VERSION | coroid_version | The release version |
COROID_BUILD_NUMBER | coroid_build_number | The build number |
COROID_RELEASE_NAME | coroid_release_name | The release name |
COROID_COMMIT_SHA | coroid_commit_sha | The full commit SHA |
COROID_ENVIRONMENT | coroid_environment | The environment key |
COROID_RELEASE_ID | coroid_release_id | The Coroid release ID |
COROID_ATTEMPT_ID | coroid_attempt_id | The deployment attempt |
GitHub rejects inputs a workflow does not declare. Coroid therefore sends
coroid_version, coroid_build_number and coroid_release_name only to a
workflow that lists them. Declare them as optional:
on:
workflow_dispatch:
inputs:
coroid_release_id: { required: true }
coroid_attempt_id: { required: true }
coroid_commit_sha: { required: true }
coroid_environment: { required: true }
coroid_version: { required: false }
coroid_build_number: { required: false }
coroid_release_name: { required: false }
jobs:
deploy:
runs-on: ubuntu-latest
env:
APP_VERSION: ${{ inputs.coroid_version || '0.0.0-dev' }}
APP_BUILD_NUMBER: ${{ inputs.coroid_build_number || '0' }}
APP_COMMIT: ${{ inputs.coroid_commit_sha || github.sha }}GitLab passes the values as variables, so no declaration is needed:
deploy:
script:
- export APP_VERSION="${COROID_VERSION:-0.0.0-dev}"
- export APP_BUILD_NUMBER="${COROID_BUILD_NUMBER:-0}"
- export APP_COMMIT="${COROID_COMMIT_SHA:-$CI_COMMIT_SHA}"A pipeline that runs on its own can use its own values. Report the version you deployed, as described below, so the release shows it.
Write a release manifest
The simplest approach that works on every platform is to write one small file during the build and read it wherever the version is shown:
cat > release.json <<EOF
{
"version": "$APP_VERSION",
"buildNumber": "$APP_BUILD_NUMBER",
"commitSha": "$APP_COMMIT",
"releaseName": "${COROID_RELEASE_NAME:-}",
"environment": "${COROID_ENVIRONMENT:-local}"
}
EOFFor a web app or a service, serve the file at /version.json. That also
gives Coroid a URL to check (see below).
Recipes
Web apps (Next.js, Vite)
Values the browser needs must be set when the bundle is built:
NEXT_PUBLIC_APP_VERSION="$APP_VERSION" NEXT_PUBLIC_APP_COMMIT="$APP_COMMIT" npm run build
VITE_APP_VERSION="$APP_VERSION" npm run buildShow process.env.NEXT_PUBLIC_APP_VERSION or import.meta.env.VITE_APP_VERSION
in the footer or an About screen, and copy release.json into the public
folder before the build.
Servers and APIs
Read the values at start-up and answer on a version endpoint:
app.get('/version.json', (_request, response) => {
response.json({
version: process.env.APP_VERSION,
buildNumber: process.env.APP_BUILD_NUMBER,
commitSha: process.env.APP_COMMIT,
});
});Docker images
Pass the values as build arguments and label the image, so the running container and the registry both know the version:
ARG APP_VERSION=0.0.0-dev
ARG APP_COMMIT=unknown
ENV APP_VERSION=$APP_VERSION APP_COMMIT=$APP_COMMIT
LABEL org.opencontainers.image.version=$APP_VERSION \
org.opencontainers.image.revision=$APP_COMMITdocker build --build-arg APP_VERSION="$APP_VERSION" --build-arg APP_COMMIT="$APP_COMMIT" .iOS
Xcode reads the version shown in the App Store from MARKETING_VERSION and
the build number from CURRENT_PROJECT_VERSION:
xcodebuild -scheme App -configuration Release archive \
MARKETING_VERSION="$APP_VERSION" \
CURRENT_PROJECT_VERSION="$APP_BUILD_NUMBER"With fastlane, use increment_version_number(version_number: ENV["APP_VERSION"])
and increment_build_number(build_number: ENV["APP_BUILD_NUMBER"]).
Android
Read the values in app/build.gradle.kts:
android {
defaultConfig {
versionName = System.getenv("APP_VERSION") ?: "0.0.0-dev"
versionCode = (System.getenv("APP_BUILD_NUMBER") ?: "1").toInt()
}
}BuildConfig.VERSION_NAME then shows the version in the app.
Flutter
flutter build appbundle --build-name="$APP_VERSION" --build-number="$APP_BUILD_NUMBER"
flutter build ipa --build-name="$APP_VERSION" --build-number="$APP_BUILD_NUMBER"Expo and React Native
Read the values in app.config.js:
export default {
expo: {
version: process.env.APP_VERSION ?? '0.0.0-dev',
ios: { buildNumber: process.env.APP_BUILD_NUMBER ?? '1' },
android: { versionCode: Number(process.env.APP_BUILD_NUMBER ?? 1) },
},
};Report the version you deployed
A deployment event can say which version and build it deployed. Add version
and buildNumber to the event your pipeline already sends:
{
"schemaVersion": 1,
"eventId": "ci:run-812:production:succeeded",
"providerRunId": "run-812",
"projectId": "<project-uuid>",
"environmentKey": "production",
"repository": "owner/repository",
"commitSha": "0123456789abcdef0123456789abcdef01234567",
"status": "succeeded",
"occurredAt": "2026-09-28T12:00:00Z",
"version": "1.4.0",
"buildNumber": "42"
}If the project's pipeline assigns versions, the release takes the reported
version. Otherwise the release page shows the reported version and points
out when it differs from the release. For a project hosted on Coroid, set
repository to the project ID. Deployment events and CI
setup describes the rest of the event.
Check what's running
Give each environment a version URL, such as
https://app.example.com/version.json. After a deployment succeeds, Coroid
opens the URL and looks for the commit SHA or the version. A reported commit
must match the release commit; otherwise the version must match. Coroid keeps
checking for ten minutes while the rollout finishes, then shows Verified,
Different version or Not reachable under What's running on the
release page.
The URL must use HTTPS and a public address. Coroid does not follow redirects and reads at most 64 KB.
Let Coroid set it up
Set up version stamping on the Versioning screen opens New Work with a
request written for the project's detected stack. An agent reads the values
above at build time, shows the version in the app, writes release.json,
declares the workflow inputs and documents it in the README. Review the
request, then continue as with any other work.