Skip to content

fix: add success-conclusions as an optional input to control what syn… - #307

Merged
Raj-StepSecurity merged 4 commits into
mainfrom
fix/optional-strictmode-for-sync-status
Sep 11, 2026
Merged

Raj-StepSecurity merged 4 commits into
mainfrom
fix/optional-strictmode-for-sync-status

Conversation

@Raj-StepSecurity

@Raj-StepSecurity Raj-StepSecurity commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

No description provided.

workflow tests updated

workflow tests updated
success-conclusions only used if syncStatus is true
@Raj-StepSecurity
Raj-StepSecurity force-pushed the fix/optional-strictmode-for-sync-status branch from 85713f9 to e8729d8 Compare September 11, 2026 10:17
@Raj-StepSecurity Raj-StepSecurity added the review-required This PR requires review label Sep 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

PR Review

Action Type

Node-based — uses node24 runtime (declared in action.yaml), compiled to dist/index.js via esbuild.


Passed Checks

  • License: LICENSE present with both StepSecurity copyright (2023) and original author Ben Coleman (2026).
  • action.yaml: File exists; no author field present (check N/A per policy).
  • SECURITY.md: Present at repo root.
  • No FUNDING.yml: Not present.
  • Required workflow files: .github/workflows/auto_cherry_pick.yml and .github/workflows/actions_release.yml both present.
  • No renovate.json: Not present.
  • No PULL_REQUEST.md: Not present.
  • No ISSUE_TEMPLATE folder: Not present.
  • No CHANGELOG.md: Not present.
  • No .vscode folder: Not present.
  • README example versions: All usage examples correctly use major-version tag only (step-security/workflow-dispatch@v1).
  • README banner: StepSecurity Maintained Action banner is present on line 1 of README.md.
  • Subscription check URL: Code calls the correct subscription endpoint.
  • Upstream variable: validateSubscription() sets const upstream = 'benc-uk/workflow-dispatch', which correctly matches original-owner: "benc-uk" + repo-name: "workflow-dispatch" from auto_cherry_pick.yml.
  • package.json author: "author": "step-security".
  • No repository field in package.json: Field absent (check N/A).
  • No unused dependencies: All devDependencies (@actions/core, @actions/github, axios, esbuild, eslint, prettier, typescript, typescript-eslint, @eslint/js) are actively used.
  • dist folder: Present.
  • Build script in package.json: "build" script is present; no need to check actions_release.yml for a script input.

Failed Checks

  • README.md missing documentation for success-conclusions: The PR adds this new input to action.yaml and fully implements it in code, but README.md's "Action Inputs" section ends at sync-status with no mention of success-conclusions. Users will not know the input exists, what values are valid, or how it interacts with sync-status.

Warnings

  • sync-status README description is now incomplete: The current text says "If the triggered workflow run fails or is cancelled, this action will also be set to failed." This is only accurate when success-conclusions is not set. When success-conclusions is set, the pass/fail logic changes fundamentally. The sync-status docs should be updated to cross-reference the new input.
  • Silent ignore when sync-status=false: If a user provides invalid success-conclusions values but leaves sync-status=false, the validation is skipped silently (by design — successConclusions stays null). This is intentional per the code comments, but it could hide typos in configs written for future use. Consider at minimum a core.warning() in this case.
  • Test job uses suspicious version comment: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd — the pinned hash is correct practice, but the comment v6.0.2 should be verified to actually match the hash. An incorrect comment erodes the audit value of pinned actions.

Security Findings

No security issues found.

  • success-conclusions input is properly sanitized: split on comma, each value trimmed, lowercased, and validated against an explicit allowlist (KNOWN_CONCLUSIONS) before any workflow is dispatched. A typo causes an early exit before the remote workflow is triggered.
  • The runStatusNow !== 'completed' guard correctly prevents a null conclusion (e.g., after a poll timeout) from being misread as success — this is the core correctness fix in the PR and it is implemented correctly.
  • Subscription validation uses process.env.GITHUB_REPOSITORY (runner-provided env var) rather than any user-supplied input, so it cannot be hijacked via workflow inputs.

Summary

The feature implementation is solid — the new success-conclusions input is correctly validated, backward-compatible, and covered by five new integration test cases. The one blocking issue is that README.md must be updated to document the new input before merging.

Comment thread action.yaml
success-conclusions:
description: 'Optional comma-separated run conclusions that sync-status treats as a pass. When set, anything not in this list fails. When not set, old behaviour is preserved (only failure and cancelled fail). Valid values: success, failure, neutral, cancelled, skipped, timed_out, action_required, stale, startup_failure.'
required: false
default: ''

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing README documentation — this new input has no entry in README.md's "Action Inputs" section. Please add a ### success-conclusions block describing:

  • what it does (comma-separated list of conclusions treated as pass)
  • valid values (success, failure, neutral, cancelled, skipped, timed_out, action_required, stale, startup_failure)
  • that it only takes effect when sync-status: true and wait-for-completion: true
  • that omitting it preserves the old behaviour (only failure/cancelled fail)

Also update the ### sync-status description to cross-reference this input, since the current wording ("fails or is cancelled") is no longer the full picture.

Comment thread src/main.ts
// If not set, successConclusions is null and legacy conclusion handling
// is preserved (failure/cancelled fail, other completed conclusions pass).
const configuredSuccessConclusions = core.getInput('success-conclusions')
const successConclusions =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The guard syncStatus && configuredSuccessConclusions means that if a user sets success-conclusions: "invalud_typo" but leaves sync-status: false, the value is silently accepted with no warning — the input is unused but the typo is invisible. Consider emitting a core.warning() when configuredSuccessConclusions is non-empty but syncStatus is false, so users catch config drift early:

Suggested change
const successConclusions =
const configuredSuccessConclusions = core.getInput('success-conclusions')
if (configuredSuccessConclusions && !syncStatus) {
core.warning("'success-conclusions' is set but 'sync-status' is false — the input will be ignored.")
}
const successConclusions =
syncStatus && configuredSuccessConclusions

@github-actions

Copy link
Copy Markdown
Contributor

PR Review

Action Type

Node-based action (uses node24 runtime with dist/index.js entry point).

✅ Passed Checks

  • License: MIT license present with both StepSecurity copyright (2023) and original author Ben Coleman copyright
  • SECURITY.md: Present with correct reporting contact
  • FUNDING.yml: Not present
  • .github/workflows: Contains both required auto_cherry_pick.yml and actions_release.yml
  • renovate.json: Not present
  • PULL_REQUEST.md: Not present
  • ISSUE_TEMPLATE folder: Not present
  • CHANGELOG.md: Not present
  • .vscode folder: Not present
  • README examples: All use @v1 (major version only — no full semver tags)
  • README banner: StepSecurity Maintained Action banner present on line 1
  • Subscription check URL: Correctly calls https://agent.api.stepsecurity.io/v1/github/$GITHUB_REPOSITORY/actions/maintained-actions-subscription
  • Upstream variable: 'benc-uk/workflow-dispatch' correctly matches original-owner: "benc-uk" + repo-name: "workflow-dispatch" from auto_cherry_pick.yml
  • package.json author: Set to "step-security"
  • dist folder: Present and updated
  • build script: Present in package.json (esbuild src/main.ts ...)
  • No unused dependencies: All devDependencies (@actions/core, @actions/github, axios, build/lint tooling) are used
  • action.yaml author field: Not present — ignored per guidelines

❌ Failed Checks

None.

⚠️ Warnings

  • Edge case in validation timing: success-conclusions is validated (and will throw on invalid values) whenever sync-status: true, even if wait-for-completion is omitted or false. In that scenario the input is never actually applied, so the error before dispatch is surprising. Consider scoping the validation to syncStatus && waitForCompletion to match the documented preconditions.
  • Duplicate API call in sync-status block: After the polling loop already fetched the run status, the syncStatus block issues a second GET /actions/runs/:id call to re-read the final status. This is pre-existing behavior, not introduced by this PR, but a minor inefficiency worth noting.

🔒 Security Findings

No security issues found. The new success-conclusions input is validated against an explicit allowlist (KNOWN_CONCLUSIONS Set) before the workflow is dispatched — a correct fail-fast approach that prevents invalid user input from affecting verdict logic. No injection vectors identified.

Summary

A well-implemented feature PR that adds a configurable success-conclusions allowlist for sync-status, with full backward compatibility preserved. The added test coverage in build-test.yaml is comprehensive, covering the happy path, rejection of invalid values, multi-value parsing, and the timeout/null-conclusion bug fix. Ready to merge pending the minor edge-case warning above.

Comment thread src/main.ts
.filter(Boolean),
)
: null
if (successConclusions) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The validation guard checks successConclusions (truthy when syncStatus && configuredSuccessConclusions), but the input is only applied when both syncStatus && waitForCompletion are true (line 186). If a user sets sync-status: true but omits wait-for-completion, an invalid success-conclusions value will throw here and abort the run before dispatch — even though the input would never be consulted. Consider tightening the condition to match the documented precondition:

Suggested change
if (successConclusions) {
if (successConclusions && waitForCompletion) {

Comment thread src/main.ts
)
} else if (successConclusions) {
// New configurable behaviour — only when success-conclusions is explicitly set
if (conclusion && successConclusions.has(conclusion)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The conclusion && guard is redundant here: we already confirmed runStatusNow === 'completed' on line 199, and a completed GitHub Actions run always carries a non-null conclusion. Removing the guard makes the intent clearer — a completed run that somehow has no conclusion is still treated as a failure, which is the correct safe default.

Suggested change
if (conclusion && successConclusions.has(conclusion)) {
if (successConclusions.has(conclusion)) {

@Raj-StepSecurity
Raj-StepSecurity merged commit 09f92a9 into main Sep 11, 2026
33 of 35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-required This PR requires review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants