Skip to content

Expose GitHub-compatible expression contexts at every workflow phase - #144

Merged
gjkim42 merged 1 commit into
mainfrom
open-actions-task-110
Aug 30, 2026
Merged

Expose GitHub-compatible expression contexts at every workflow phase#144
gjkim42 merged 1 commit into
mainfrom
open-actions-task-110

Conversation

@gjkim42

@gjkim42 gjkim42 commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

What type of PR is this?

/kind api

What this PR does / why we need it:

  • defines one phase-aware expression availability contract shared by workflow validation, planning, and runner evaluation
  • exposes the supported GitHub, job, strategy, action, steps, needs, and environment context values at their documented workflow phases
  • defers needs-dependent job planning until prerequisite jobs are terminal while preserving early validation for expressions that can be evaluated immediately
  • validates composite-action expressions and outputs, isolates the env context to workflow-defined values, and preserves exact numeric values in event payloads
  • records rerun triggering actors in the WorkflowRun API and generated CRD so github.triggering_actor is accurate
  • documents the supported context surface and runner plan version 9

Which issue(s) this PR is related to:

Fixes #110

Special notes for your reviewer:

The expression availability table is covered by conformance tests to keep validation and runtime context construction aligned.

Validation completed:

  • make update
  • make test
  • make verify
  • make build

Does this PR introduce a user-facing change?

Open Actions now exposes GitHub-compatible expression contexts across workflow planning and execution, including expanded GitHub metadata, job status, strategy metadata, action metadata, and rerun triggering actors.

@gjkim42

gjkim42 commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator Author

/kelos claude-api-review

@gjkim42 gjkim42 self-assigned this Aug 30, 2026
@kelos-bot

kelos-bot Bot commented Aug 30, 2026

Copy link
Copy Markdown

🤖 Kelos Task Status

Task open-actions-claude-api-reviewer-issue-comment-1300a672fa4e has succeeded. ✅

@gjkim42 gjkim42 added triage-accepted Accepted for triage priority/important-soon High-priority work to address soon labels Aug 30, 2026
@kelos-bot

kelos-bot Bot commented Aug 30, 2026

Copy link
Copy Markdown

🤖 Open Actions Claude API Reviewer Agent @gjkim42

API Design Review

Verdict: APPROVE
Scope: Re-review after 724995d — phase-aware expression availability contract shared by validation/planning/runtime, expanded github/job/strategy/steps/env context values, deferred needs-based job planning, spec.rerun.triggeringActor on WorkflowRun, and runner plan version 9 (28 files, +1629/−363).

The blocking finding from the previous review is resolved, and I verified each fix in the code rather than from the description. No P0/P1 issues remain; the leftover items below are optional and were already reasonably triaged.

Findings

Compatibility — prior blocking finding resolved

  • internal/controller/workflowrun_controller.go:2438-2448jobPlanned now excludes WorkflowJobs matching the result-placeholder shape via deferredJobResultPlaceholderMatches (line 2628) instead of counting any child under the logical ID. A reconcile retry after an interrupted placeholder status write (or a controller restart between the create and the status update) re-evaluates the job condition and completes the placeholder, rather than executing a matrix job that GitHub semantics require to be skipped or terminally failing a non-matrix run on the full-spec identity check. All three identity checks in completeDeferredJobPlanning (lines 2577, 2589) use the same matcher, so the create-conflict recovery path is covered too. This restores the recovery contract documented in docs/reference.md.
  • internal/controller/workflowrun_controller.go:2628-2639 — placeholder matching accepts both the deferred-planning sentinel and the previously persisted matrix-evaluation sentinel, so nonterminal placeholders created before a controller upgrade remain reconcilable. TestReconcileDeferredJobsCompletesExistingResultPlaceholder (workflowrun_controller_test.go:1540) covers the non-matrix, matrix, and persisted-sentinel cases and asserts that completing a placeholder creates no executable children.

Naming and documentation — resolved

  • The frozen wire names now carry compatibility comments: api/v1alpha1/labels.go:19-21 (actions.kelos.dev/matrix-plan), deferredJobPlanKey (matrix.json), workflowPlanManifest.DeferredJobs (json:"matrices"), and the matrix-plan ConfigMap name suffix. This records that the stored values must not follow future Go-identifier renames.

GitHub Actions compatibility — resolved

  • internal/workflowcontext/context.go:224 — the synthetic github.repositoryUrl fallback now emits GitHub's documented git://<host>/<owner>/<repo>.git form; the event payload's repository.git_url remains the primary source. Tested in TestRepositoryURLUsesGitProtocol.

API surface (unchanged since prior round)

  • api/v1alpha1/workflowrun_types.go:141-148spec.rerun.triggeringActor is additive, optional, and mirrors the existing spec.source.github.actor validation; the generated chart CRD matches the markers, and no deepcopy changes are needed for a plain string field.

Suggestions (optional)

  • Non-matrix strategy/matrix remaining empty diverges from the hosted runner's commonly observed degenerate values (job-total: 1, fail-fast: true, …). The triage that this is observational rather than a documented GitHub contract is defensible under the docs-as-spec policy; an empirical check against a live run, or a tracking issue if divergence is confirmed, would close the loop.
  • internal/workflowcontext/context.go:69-75secret_source is inferred as Dependabot from the actor login and never reports None; documenting the supported values in docs/reference.md would keep it precise.
  • The runsOn sentinel is still a magic value on a user-meaningful field, but the dual-sentinel matcher removes the upgrade fragility; a dedicated placeholder marker (label/annotation) remains a possible future cleanup.

/kelos needs-input

@gjkim42

gjkim42 commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the current Claude API review findings in 724995d:

  • deferred planning now distinguishes a nonterminal result placeholder from a planned job, so condition evaluation is retried after an interrupted status write
  • placeholder identity matching accepts both persisted matrix-evaluation and deferred-planning sentinels across controller upgrades
  • table coverage exercises non-matrix, matrix, and persisted-sentinel recovery without creating executable children for a skipped job
  • persisted matrix-plan, matrix.json, matrices, and matrix-plan suffix values now have compatibility comments
  • synthetic github.repositoryUrl values use GitHub's documented git:// form

Triaged without code changes:

  • non-matrix strategy defaults are observational rather than a documented GitHub contract; the current GitHub reference describes strategy as matrix execution metadata
  • the exported Go constant rename remains intentional for the v1alpha1 source API; its stored wire value is frozen
  • the secret_source and tracking-link notes were optional documentation suggestions and are not required for this change

Validation: make update, make test, make verify, and make build.

@gjkim42

gjkim42 commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator Author

/kelos claude-api-review

@gjkim42

gjkim42 commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator Author

/kelos claude-review

@kelos-bot

kelos-bot Bot commented Aug 30, 2026

Copy link
Copy Markdown

🤖 Kelos Task Status

Task open-actions-claude-reviewer-issue-comment-be02d623b485 has succeeded. ✅

@kelos-bot

kelos-bot Bot commented Aug 30, 2026

Copy link
Copy Markdown

🤖 Open Actions Claude Reviewer Agent @gjkim42

Review Summary

Verdict: APPROVE
Overall correctness: patch is correct
Scope: Defines one phase-aware expression availability contract shared by validation, planning, and runner evaluation; expands the github, job, strategy, steps, and env context surface; defers planning for jobs whose name, runs-on, timeout, or matrix reads needs; records rerun triggering actors in the WorkflowRun API; and bumps the runner plan to version 9.

Findings Overview

Priority Count File:Line Summary
P0 0 none
P1 0 none
P2 1 internal/runner/expression.go:150 job.status is always success in composite fields and action input defaults
P3 0 none

Findings

GitHub Actions compatibility

  • [P2] internal/runner/expression.go:150job.status evaluates to success inside composite action fields, composite outputs, and action input defaults regardless of the job's actual status. compositeExpressionContext (expression.go:150) and resolveActionDefaultExpression (expression.go:29) pass a nil status into expressionContext, and expressionStatus(nil) (expression.go:247) returns success, whereas workflowExpressionContext (expression.go:143) falls back to state.jobStatus for the same situation. When a step gated by if: always() or if: failure() invokes a composite action after an earlier step failed — a common cleanup pattern — ${{ job.status }} in the composite's step fields, outputs, or an action's input default resolves to success, while GitHub reports failure ("The current status of the job" per the contexts reference), and docs/reference.md:862 states "status reflects the job's current success, failure, or cancelled state." Falling back to &compositeContext.state.jobStatus when status is nil mirrors the workflow-step path for the composite sites; the input-default path needs the status threaded into actionInputsForAction, or the documentation should scope the claim until it does.

Key takeaways

  • The availability table in internal/workflow/expression_context.go was checked row by row against GitHub's documented context-availability table; every workflow-file site matches (with open_actions as a declared extension), and the conformance test pins each site. The job context additions (workflow_ref, workflow_sha, workflow_repository, workflow_file_path) match the current GitHub contexts reference, and the unsupported properties (container, services, check_run_id) are documented with rationale.
  • The plan version 9 decode invariant holds on every emit path: spec.workflowPath is a required CRD field, plan.Strategy is set exactly when a matrix combination is, and empty matrix include entries are rejected during resolution, so an empty-but-non-nil combination cannot trip the omitempty pairing check in DecodePlan.
  • The switch to json.Number event decoding was traced to every consumer: expression normalization, EventID/EventString, deferred-plan round-trips, and the GitHub-compatible number bound all handle it, and no float64 type assertions remain outside tests.
  • Deferred non-matrix planning, result-placeholder recovery (including the persisted matrix-evaluation sentinel), job-concurrency evaluation with a settled needs context, env-context isolation with GITHUB_ENV propagation at all three command paths, and the rerun triggeringActor webhook wiring are all covered by tests that exercise the positive paths.
  • Items triaged in the earlier API review round (non-matrix strategy degenerate values, the runs-on sentinel, secret_source documentation) were not re-raised.

Define one phase-aware availability contract for workflow validation, planning, and runner evaluation. Populate documented GitHub, job, strategy, action, steps, needs, and environment context values, including rerun triggering actors and current job status in action metadata expressions. Defer needs-dependent job planning safely across controller retries and preserve stored planning wire compatibility.
@gjkim42
gjkim42 force-pushed the open-actions-task-110 branch from 724995d to f612d69 Compare August 30, 2026 11:56
@gjkim42

gjkim42 commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the latest P2 finding in the squashed commit f612d69:

  • composite fields and outputs now inherit the execution state's current job.status when they do not have a narrower condition status
  • action input-default evaluation receives the current job status through action invocation
  • TestCompositeActionUsesCurrentJobStatusAfterFailure covers a cleanup composite invoked with always() after a failed step, including its input default, step expression, and output

The API review and all remaining general-review findings are approved or optional. The PR branch now contains exactly one commit.

Validation: make update, targeted test, make test, make verify, and make build.

@gjkim42
gjkim42 added this pull request to the merge queue Aug 30, 2026
Merged via the queue into main with commit 0ec9bb2 Aug 30, 2026
9 checks passed
@gjkim42
gjkim42 deleted the open-actions-task-110 branch August 30, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose GitHub-compatible expression contexts at every workflow phase

1 participant