Conversation
ChristopherHX
left a comment
There was a problem hiding this comment.
I know this is a draft and I am not part of GitHub, tested this interesting thing anyway
| // Emit start marker before condition evaluation | ||
| if (emitCompositeMarkers) | ||
| { | ||
| ExecutionContext.Output($"##[start-action display={EscapeProperty(SanitizeDisplayName(step.DisplayName))};id={EscapeProperty(stepId)}]"); |
There was a problem hiding this comment.
display Name is wrong in composite even if not using expressions, this value is updated later again as this may change if this depends on a changing context variable:
(Logs generated with custom cli tool + env variable)
Currently looks like in the log the displayname is not the expected one
[.github/workflows/test.yml / _] Running: Run ./
| Prepare all required actions
| ##[group]Run ./
| ##[endgroup]
| ##[start-action display=run;id=__run]
| ##[group]Run echo "Hello, World"
| echo "Hello, World"
| shell: /bin/bash --noprofile --norc -e -o pipefail {0}
| ##[endgroup]
| Hello, World
| ##[end-action id=__run;outcome=success;conclusion=success;duration_ms=44]
| ##[start-action display=run;id=__run_2]
| ##[group]Run echo "Hello, World"
| echo "Hello, World"
| shell: /bin/bash --noprofile --norc -e -o pipefail {0}
| ##[endgroup]
| Hello, World
| ##[end-action id=__run_2;outcome=success;conclusion=success;duration_ms=37]
[.github/workflows/test.yml / _] Succeeded: Run ./
Action
runs:
using: composite
steps:
- name: Hello World
run: echo "Hello, World"
shell: bash
- run: echo "Hello, World"
shell: bashMinimally this is required for this to be acceptable for me as an actions user.
| ExecutionContext.Output($"##[start-action display={EscapeProperty(SanitizeDisplayName(step.DisplayName))};id={EscapeProperty(stepId)}]"); | |
| step.TryUpdateDisplayName(out _); | |
| ExecutionContext.Output($"##[start-action display={EscapeProperty(SanitizeDisplayName(step.DisplayName))};id={EscapeProperty(stepId)}]"); |
After Constant Hello World is the display name or the fallback
[.github/workflows/test.yml / _] Running: Run ./
| Prepare all required actions
| ##[group]Run ./
| ##[endgroup]
| ##[start-action display=Hello World;id=__run]
| ##[group]Run echo "Hello, World"
| echo "Hello, World"
| shell: /bin/bash --noprofile --norc -e -o pipefail {0}
| ##[endgroup]
| Hello, World
| ##[end-action id=__run;outcome=success;conclusion=success;duration_ms=35]
| ##[start-action display=Run echo "Hello, World";id=__run_2]
| ##[group]Run echo "Hello, World"
| echo "Hello, World"
| shell: /bin/bash --noprofile --norc -e -o pipefail {0}
| ##[endgroup]
| Hello, World
| ##[end-action id=__run_2;outcome=success;conclusion=success;duration_ms=27]
[.github/workflows/test.yml / _] Succeeded: Run ./
Don't you need to expand the proposal with an update displayname command additionally to start-action or postpone issueing this log info.
runner/src/Runner.Worker/StepsRunner.cs
Lines 195 to 199 in 6680090
There was a problem hiding this comment.
I haven't tested yet 😄
Will look into this during E2E testing (needs server changes to render)
## Summary Emit `##[start-action]` / `##[end-action]` markers in the log stream around each nested step inside a composite action. The UI parses these markers to render collapsible regions, giving users visibility into individual steps that were previously hidden in a single opaque log blob. ## Design The runner writes `##[` markers directly to the log stream via `ExecutionContext.Output()`, bypassing the logging command pipeline. No new `::` logging command is registered. Users cannot emit these markers from scripts. ### Marker format ``` ##[start-action display=<step-display-name>;id=<step-id>] ... step output ... ##[end-action id=<step-id>;outcome=<result>;conclusion=<result>;duration_ms=<ms>] ``` - **id** — the step's `ContextName` (from YAML `id:` or auto-generated with `__` prefix) - **outcome** — raw result before `continue-on-error` is applied - **conclusion** — final result after `continue-on-error` - **duration_ms** — wall-clock milliseconds (0 for skipped steps) Nested composites use dot-separated IDs (e.g. `outer.inner-step`) to keep each step globally unique. ### Feature flag Gated behind `actions_runner_emit_composite_markers` (job message variable) with `ACTIONS_RUNNER_EMIT_COMPOSITE_MARKERS` env var fallback (for internal testing only). ### Injection prevention `OutputManager.OnDataReceived` replaces `##[start-action` and `##[end-action` from user process stdout/stderr with `##[\start-action` and `##[\end-action`. This preventing users from injecting fake markers. The runner's own markers bypass `OutputManager` entirely since they're written via `ExecutionContext.Output()` directly.
c7780a8 to
2a1588d
Compare
Summary
Emit
##[start-action]/##[end-action]markers in the log stream around each nested step inside a composite action. The UI parses these markers to render collapsible regions, giving users visibility into individual steps that were previously hidden in a single opaque log blob.Design
The runner writes
##[markers directly to the log stream viaExecutionContext.Output(), bypassing the logging command pipeline. No new::logging command is registered. Users cannot emit these markers from scripts.Marker format
ContextName(from YAMLid:or auto-generated with__prefix)continue-on-erroris appliedcontinue-on-errorNested composites use dot-separated IDs (e.g.
outer.inner-step) to keep each step globally unique.Feature flag
Gated behind
actions_runner_emit_composite_markers(job message variable) withACTIONS_RUNNER_EMIT_COMPOSITE_MARKERSenv var fallback (for internal testing only).Injection prevention
OutputManager.OnDataReceivedreplaces##[start-actionand##[end-actionfrom user process stdout/stderr with##[\start-actionand##[\end-action. This preventing users from injecting fake markers. The runner's own markers bypassOutputManagerentirely since they're written viaExecutionContext.Output()directly.