Variables, Secrets & Step Outputs | FlightStack
Variables, Secrets & Step Outputs
Section titled “Variables, Secrets & Step Outputs”FlightStack pipelines have three sources of dynamic data:
- Variables — configuration values (org / repo / pipeline scoped).
- Secrets — variables flagged
isSecret: true, encrypted at rest, masked in logs. - Step outputs — values emitted by upstream jobs and consumed downstream.
All three are read with the same ${{ ... }} syntax.
Expression syntax
Section titled “Expression syntax”| Expression | Resolves to |
|---|---|
${{ vars.API_BASE_URL }} | Variable named API_BASE_URL from the resolved scope. |
${{ secrets.SENTRY_DSN }} | Secret. Available only on the agent at execution time. |
${{ steps.<jobId>.outputs.<name> }} | Output <name> from a previously executed job. |
${{ context.branch }} | Run context (branch, commit, eventType, …). |
Expressions can appear in:
- Job inputs (e.g. an Android keystore alias from a secret)
- Shell-job command strings
- Notification message bodies and webhook URLs
- Connection
conditionfields (see Connections)
Variable scopes
Section titled “Variable scopes”| Scope | Defined on | Inheritance |
|---|---|---|
| Organization | An organization | All repos and pipelines in that org |
| Repository | A connected repo | All pipelines on that repo |
| Variable group | A named bag | Any pipeline that attaches the group |
| Pipeline | A single pipeline | Only that pipeline’s runs |
| Per-run | POST /build body | One specific build only |
Scope resolution
Section titled “Scope resolution”When a pipeline runs, FlightStack composes variables in this order (later overrides earlier):
- Organization-scoped variables
- Variable groups attached to the pipeline
- Repository-scoped variables
- Pipeline-scoped variables
- Per-run overrides
The same rule applies to secrets.
Step outputs
Section titled “Step outputs”Each job can emit named outputs. Downstream jobs reference them with
${{ steps.<jobId>.outputs.<name> }}.
Declaring outputs in the step spec
Section titled “Declaring outputs in the step spec”In your step’s spec (marketplace step or custom step):
outputs: - name: deployedUrl description: Public URL after deploy - name: changedCount description: Number of screenshots that changedEmitting outputs from a job
Section titled “Emitting outputs from a job”Inside a shell job (or any custom step), use the fs-output helper:
fs-output deployedUrl "https://acme.web.app"fs-output changedCount 3fs-output is on the agent’s PATH automatically. It writes to the run’s output sink and
sends them back to the server via
POST /Pipeline/job-runs/{jobRunId}/outputs.
Reading outputs downstream
Section titled “Reading outputs downstream”Reference by <jobId> — the ID you assigned the upstream job in the pipeline definition,
not the human-readable name:
# Notify jobinputs: message: | Deploy finished: ${{ steps.deploy.outputs.deployedUrl }} ScreenStack diffs: ${{ steps.screen.outputs.changedCount }}Inputs (FS_IN_*)
Section titled “Inputs (FS_IN_*)”Every job is invoked with its declared inputs exposed as FS_IN_* environment variables on
the agent. So an input named flutterVersion becomes FS_IN_FLUTTER_VERSION. Useful for
shell jobs that consume configured inputs without doing their own templating:
echo "Building with Flutter $FS_IN_FLUTTER_VERSION"flutter pub getThis mirrors the well-known INPUT_* convention from GitHub Actions, with our FS_IN_
prefix.
Built-in context
Section titled “Built-in context”| Expression | Value |
|---|---|
context.repository | Full repo name (e.g. acme/mobile). |
context.branch | Branch being built. |
context.commit | Full commit SHA. |
context.commitShort | Short SHA (7 chars). |
context.commitMessage | First line of the commit message. |
context.author | Commit author name. |
context.eventType | push, tag, pullRequest, manual, schedule. |
context.runNumber | Pipeline run number. |
context.runId | UUID of the run. |
context.timestamp | ISO-8601 run start time. |
Secrets
Section titled “Secrets”Secrets are decrypted only on the agent, at the moment of execution, and shredded when the job ends.
For code-signing material (keystores, provisioning profiles, App Store Connect keys, Play service accounts, Firebase configs), use the dedicated code-signing vault rather than secrets — it’s better suited to binary blobs and adds expiration tracking.
Managing variables
Section titled “Managing variables”In the app
Section titled “In the app”- Navigate to Settings → Variables at the org, repo, or pipeline level.
- Add Variable or Add Secret, set the key/value, save.
Via API
Section titled “Via API”See Secrets API.
Best practices
Section titled “Best practices”- Use secrets for anything sensitive. Plain variables are visible in the dashboard.
- Name in uppercase with underscores —
PROD_API_KEY, notprodKey. - Scope appropriately. Don’t lift repo-specific values to the org.
- Prefer step outputs over re-deriving — once a job emits
version, downstream jobs should consume it instead of recomputing. - Rotate periodically. Audit who has access on a cadence.
See also
Section titled “See also”- Connections → conditional — use expressions to branch flow
- Secrets management guide — operational patterns
- Code signing — the right home for keystores and signing keys
- Secrets API — programmatic management