Skip to content

Comments

Composite Action Step Markers#4243

Open
ericsciple wants to merge 1 commit intomainfrom
users/ericsciple/26-02-composite-markers
Open

Composite Action Step Markers#4243
ericsciple wants to merge 1 commit intomainfrom
users/ericsciple/26-02-composite-markers

Conversation

@ericsciple
Copy link
Collaborator

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.

Copy link
Contributor

@ChristopherHX ChristopherHX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is a draft and I am not part of GitHub, tested this interesting thing anyway

@ericsciple ericsciple force-pushed the users/ericsciple/26-02-composite-markers branch 2 times, most recently from 8abb2f4 to cef1d03 Compare February 20, 2026 01:16
@ericsciple ericsciple marked this pull request as ready for review February 20, 2026 01:16
Copilot AI review requested due to automatic review settings February 20, 2026 01:16
@ericsciple ericsciple requested a review from a team as a code owner February 20, 2026 01:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for emitting collapsible step markers in composite action logs. The UI can parse ##[start-action] and ##[end-action] markers to render individual nested steps that were previously hidden in a single opaque log blob.

Changes:

  • Added feature flag actions_runner_emit_composite_markers with environment variable fallback for internal testing
  • Implemented marker injection prevention by escaping user-emitted markers in OutputManager
  • Added marker emission in CompositeActionHandler around each nested step with timing and outcome tracking

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Runner.Common/Constants.cs Added feature flag constant and environment variable name for composite markers
src/Runner.Common/ActionCommand.cs Added public EscapeValue method to escape special characters in marker properties
src/Runner.Worker/Handlers/OutputManager.cs Added injection prevention by replacing user-emitted ##[start-action and ##[end-action with escaped versions
src/Runner.Worker/Handlers/CompositeActionHandler.cs Implemented marker emission with step ID generation, timing tracking, and outcome/conclusion reporting
src/Test/L0/Worker/OutputManagerL0.cs Added tests for marker injection prevention in user output
src/Test/L0/Worker/Handlers/CompositeActionHandlerL0.cs Added comprehensive tests for escaping, sanitization, marker format, and result mapping

@ericsciple ericsciple marked this pull request as draft February 20, 2026 01:40
@ericsciple ericsciple force-pushed the users/ericsciple/26-02-composite-markers branch 5 times, most recently from 86faaeb to 648fa57 Compare February 20, 2026 02:38
@ericsciple ericsciple force-pushed the users/ericsciple/26-02-composite-markers branch from 648fa57 to 2ccceb8 Compare February 20, 2026 02:39
@ericsciple ericsciple marked this pull request as ready for review February 20, 2026 02:42
@ChristopherHX
Copy link
Contributor

You need to take a look at actions with post steps within composite actions, like actions/cache@v4.

  • The step id of root level becomes a uuid
    • probably irrelevant, since the end marker use the same id
  • the display name is the initially invalid one again namely "run" instead of Run actions/cache@v4
  • tested both local and remote composite actions (look equally broken)
  • tested both skipped post step and executed post step (no difference in display name)
| ##[start-action display=Run actions/cache@v4;id=__self.__actions_cache]
| ##[group]Run actions/cache@v4
| with:
|   enableCrossOsArchive: false
|   fail-on-cache-miss: false
|   lookup-only: false
|   save-always: false
| ##[endgroup]
| ##[error]Input required and not supplied: key
| ##[end-action id=__self.__actions_cache;outcome=failure;conclusion=failure;duration_ms=148]
[.github/workflows/test.yml / _] Failed: Run ./
[.github/workflows/test.yml / _] Running: Post Run ./
| Post job cleanup.
| ##[start-action display=run;id=__ca4435ec-3068-4fdf-9051-7de2dd4c7686.__actions_cache]
| ##[end-action id=__ca4435ec-3068-4fdf-9051-7de2dd4c7686.__actions_cache;outcome=skipped;conclusion=skipped;duration_ms=0]

Pre and Main step markers look good now.

@ericsciple
Copy link
Collaborator Author

ericsciple commented Feb 20, 2026

Thanks @ChristopherHX, good catch!

The step id of root level becomes a uuid
probably irrelevant, since the end marker use the same id

I just tested E2E with the UI changes and as you said, the marker IDs match so rendering is fine.

the display name is the initially invalid one again namely "run" instead of Run actions/cache@v4

Since it's scoped to post-steps only, I will likely address in a follow-up PR. That will keep this diff easier for reviewers. I'm not sure yet how messy the fix will be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants