Steps টেমপ্লেট
CI/CD পাইপলাইন ও মাল্টি-স্টেজ ওয়ার্কফ্লোর জন্য ডিজাইন করা একটি ধাপ-ভিত্তিক টেমপ্লেট। একটি ম্যাট্রিক্স ইন্ডিকেটর দিয়ে সমান্তরাল জব ভিজ্যুয়ালাইজ করে।

Fields
| Field | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
template | string | Required. Must be "steps" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
progress | float | Required. Value between 0.0 and 1.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
current_step | integer | Required. The step currently running, counting from 1 (so 1 is the first entry of step_labels); 0 means nothing has started yet. Shown in the header as current_step/total_steps. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
total_steps | integer | Required. Total number of jobs in the workflow | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
step_rows | integer[] | Parallel jobs per step (e.g. [1,1,3,1] for a 3-job matrix at step 3). Length must equal total_steps. Each value must be between 1 and 10. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
step_labels | string[] | Optional labels for each step (e.g. ["Build","Test","Deploy"]). When provided and total_steps is 6 or fewer, labels appear below each segment bar. Length must equal total_steps. Each label max 32 characters. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
state | string | Current job name (e.g. "Build Container Image") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
icon | string | SF Symbol name or MDI icon with mdi: prefix (e.g. "mdi:source-branch") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
subtitle | string | Context subtitle (e.g. "repo / CI/CD") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
accent_color | string | Named color or hex | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
url | string | Primary URL -- tappable button on the Live Activity (e.g. link to workflow run) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
secondary_url | string | Secondary URL -- second tappable button (e.g. link to commit) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
background_color | string | Background color override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
text_color | string | Text color override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| অ্যাপ সংস্করণ 1.3.3-এ আসছে | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
step_weights | number[] | Gives each step a relative width. On its own it renders a single row of proportional segments (e.g. [1, 2, 1] makes the middle step twice as wide as its neighbours). Combined with step_rows it widths the matrix columns while each column keeps its fan-out. Length must equal total_steps. See Segmented layout. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
step_colors | string[] | Per-step colors for the segmented layout (named color or hex). Length must equal total_steps. An empty entry ("") falls back to accent_color for that segment, so you can tint just a few steps. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| অ্যাপ সংস্করণ 1.3.5-এ আসছে | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
live_progress | boolean | When true, iOS animates the current step toward completion and counts down an ETA, natively, between your pushes. Requires end_date. See Live progress. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duration | integer | string | How long the current step takes: seconds (5400) or a duration string ("90m", "1h30m"). Sets start_date to now and end_date to now + duration, which is how you re-anchor the animation on each step change. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end_date | integer | Unix timestamp when the current step is expected to finish -- not the end of the whole run. Wins over duration when both are sent. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
start_date | integer | Unix timestamp when the current step began. Set for you by duration; the bar fills across start_date to end_date. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example Payload
{
"state": "ongoing",
"content": {
"template": "steps",
"progress": 0.375,
"state": "Build Container Image",
"icon": "arrow.triangle.branch",
"subtitle": "pushward-server / CI/CD",
"current_step": 2,
"total_steps": 8,
"step_rows": [1, 1, 3, 1, 1, 2, 1, 1],
"step_labels": ["Lint", "Build", "Test", "Scan", "Publish", "Deploy", "Verify", "Notify"],
"accent_color": "green"
}
}Step Rows
The step_rows array defines how many parallel jobs exist at each step. This creates a matrix visualization on the Live Activity:
// [1, 1, 3, 1, 1, 2, 1, 1]
// Step 1: ● (1 job)
// Step 2: ● (1 job)
// Step 3: ● ● ● (3 parallel jobs)
// Step 4: ● (1 job)
// Step 5: ● (1 job)
// Step 6: ● ● (2 parallel jobs)
// Step 7: ● (1 job)
// Step 8: ● (1 job)If step_rows is omitted, every step is treated as a single job. The counter still shows current_step/total_steps.
Segmented layout
এই বিভাগে একটি অ্যাপ আপডেটের একটি ফিচার বর্ণনা করা হয়েছে, যা App Store পর্যালোচনার অপেক্ষায় রয়েছে। আপডেটটি লাইভ হওয়ার সঙ্গে সঙ্গেই এটি এখানে স্বয়ংক্রিয়ভাবে আনলক হয়ে যাবে।
Set step_weights to render the steps as a single row of proportional segments instead of the equal-width matrix. Each weight is that step's relative share of the bar width, so [1, 2, 1] gives a narrow-wide-narrow layout. This suits a linear process whose stages take different amounts of time (a wash cycle, a multi-part checkout) more than a CI matrix.
In this layout the shared progress field fills the current segment fractionally: completed steps are filled solid, the current_step segment fills to progress (0.0-1.0), and later steps stay empty. Pair it with step_colors to give each stage its own tint; leave an entry blank to fall back to accent_color.
Send step_weights and step_rows together for a weighted matrix: each column's width follows its weight while it still stacks its parallel jobs. Both arrays must be length total_steps. Weights alone give the single segmented row; step_rows alone gives the equal-width matrix.
{
"state": "ongoing",
"content": {
"template": "steps",
"state": "Drying",
"icon": "dishwasher",
"subtitle": "Eco cycle",
"current_step": 3,
"total_steps": 3,
"progress": 0.5,
"step_labels": ["Wash", "Rinse", "Dry"],
"step_weights": [1, 2, 1],
"step_colors": ["blue", "teal", "orange"],
"accent_color": "teal"
}
}Weighted matrix
Send step_weights alongside step_rows to keep the parallel-jobs matrix but size each column by how long its step runs. Below, Build and Test dominate the width, Test fans out to three jobs, and each column is tinted by step_colors.
{
"state": "ongoing",
"content": {
"template": "steps",
"state": "Test",
"icon": "arrow.triangle.branch",
"subtitle": "my-app / CI/CD",
"current_step": 3,
"total_steps": 6,
"progress": 0.5,
"step_labels": ["Lint", "Build", "Test", "Scan", "Publish", "Deploy"],
"step_rows": [1, 1, 3, 1, 1, 1],
"step_weights": [15, 180, 90, 45, 20, 60],
"step_colors": ["purple", "blue", "yellow", "orange", "green", "green"],
"accent_color": "green"
}
}Live progress
এই বিভাগে একটি অ্যাপ আপডেটের একটি ফিচার বর্ণনা করা হয়েছে, যা App Store পর্যালোচনার অপেক্ষায় রয়েছে। আপডেটটি লাইভ হওয়ার সঙ্গে সঙ্গেই এটি এখানে স্বয়ংক্রিয়ভাবে আনলক হয়ে যাবে।
By default the bar only moves when you push an update, so a long step looks frozen in between. If you know how long the current step takes -- a 90-minute wash cycle, a 4-minute test suite -- set live_progress: true and tell the server when that step ends. iOS then fills the current step and counts an ETA down natively on the device, with no extra pushes.
The easiest way is duration, which the server turns into start_date = now and end_date = now + duration. Send it again whenever you advance current_step, and the animation re-anchors to the new step.
- The ETA describes the current step, not the whole run. Steps before it stay filled solid; steps after it stay empty.
- While it is counting, the ETA takes the header and the
current_step/total_stepscounter moves down beside the step name. Leavelive_progressoff and the counter keeps the header. - It works in every layout: the matrix column, the weighted column, and the segmented bar. In a fan-out column all the parallel jobs fill together, since they share one step deadline.
- If a step overruns its estimate without an update, its bar stops at full rather than racing ahead -- a stuck step never advances the counter on its own.
- Updates are merge-patches, so the anchors carry forward. Ending the activity clears them for you; on a mid-run update that should stop the animation, clear them explicitly with
"end_date": null, "live_progress": null. - Send
durationonly whencurrent_stepchanges. Restamping the window on every update makes each one a high-priority push that skips update coalescing, and snaps the bar back to empty.
live_progress requires end_date (or duration, which resolves to one). Without it there is nothing to animate toward, so the server rejects live_progress: true with 422.
Sending duration on every update would restamp start_date to now each time and snap the bar back to empty. Send it once per step -- when current_step changes -- and let the anchors carry forward in between.
{
"state": "ongoing",
"content": {
"template": "steps",
"state": "Heating water",
"icon": "dishwasher",
"subtitle": "Eco 50",
"current_step": 2,
"total_steps": 4,
"step_labels": ["Pre-wash", "Wash", "Rinse", "Dry"],
"step_weights": [1, 6, 1, 2],
"live_progress": true,
"duration": "90m",
"accent_color": "teal"
}
}Typical Flow
- Start: Set
current_step: 0,progress: 0.0(nothing running yet) - Each step: Increment
current_step(1= first step), updateprogressandstatewith the current job name - End: Set
state: "ended"withprogress: 1.0
Buttons & tap targets
Renders url_action and secondary_url_action as buttons under the segment bar; background taps invoke tap_action. The legacy url / secondary_url strings still work, but the structured action lets you attach silent-webhook acknowledgements (e.g. "Cancel job" → POST to your CI's cancel endpoint). See Tap actions for the action object shape.
Integrations Using This Template
- GitHub Actions — maps workflow jobs to steps
- Home Assistant — configurable via the
templateoption in entity config