build(workflows): avoid Argument list too long in markdown_links/markdown_src_attributes - #13838
Draft
Planeshifter wants to merge 1 commit into
Draft
build(workflows): avoid Argument list too long in markdown_links/markdown_src_attributes#13838Planeshifter wants to merge 1 commit into
Argument list too long in markdown_links/markdown_src_attributes#13838Planeshifter wants to merge 1 commit into
Conversation
…`markdown_src_attributes` The jobs `Log results` (workflow `markdown_src_attributes`) and `Check links against database` (workflow `markdown_links`) failed on scheduled `develop` runs with `An error occurred trying to start process '/usr/bin/bash' ... Argument list too long`. Root cause: PR #12741 (shell-injection hardening) routed large untrusted JSON payloads (broken-link/broken-image lists, sometimes over 200 KB) through step-level `env:` blocks instead of interpolating them into the run script text. Setting such a value as an `env:` var forces it into the OS process environment table at `execve()` time, which exceeds Linux's per-string argument/environment size limit (`MAX_ARG_STRLEN`) and crashes the runner's attempt to spawn `bash` for the step. This commit replaces every `env: VAR: ${{ steps.results.outputs.X }}` + `"$VAR"` pattern in both workflows with a quoted heredoc that writes the value directly into the run script body (`cat > file <<'DELIM' ... DELIM`). Because the heredoc body becomes part of the script file rather than the process environment or argv, it is not subject to the exec-time size limit. A quoted delimiter disables all shell parameter/command substitution on the body, so the fix also preserves the injection protection PR #12741 was introducing, via a size-safe mechanism instead of `env:`. `.github/workflows/scripts/markdown_links/create_broken_link_issues` is updated to accept a file path instead of an inline JSON string as its first argument, since passing the payload as a literal command-line argument is subject to the same exec-time limit. Also fixes a masked pre-existing bug in `markdown_src_attributes.yml`: the `Check status` step's `if: ${{ steps.results.outputs.status }} != 'success'` wraps only the left-hand operand in `${{ }}`, so the condition is always a non-empty (truthy) literal string regardless of the actual status. This step was unreachable while the `Log results` step crashed first; fixing the `Argument list too long` failure alone would have surfaced this bug as the job's new, unconditional failure point. Corrected to `${{ steps.results.outputs.status != 'success' }}`, matching the already-correct form in `markdown_links.yml`. Ref: https://github.com/stdlib-js/stdlib/actions/runs/30675870949 Ref: https://github.com/stdlib-js/stdlib/actions/runs/30675418090
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This pull request:
markdown_linksandmarkdown_src_attributesscheduled workflows, which have failed on everydeveloprun since 2026-07-01 withArgument list too longenv:-block payloads with quoted heredocs that write directly into the run script, avoiding the exec-time argument/environment size limit while preserving shell-injection protectionif:condition inmarkdown_src_attributes.ymlthat made the "Check status" step always run regardless of actual statusRelated Issues
This pull request does not have any related issues.
Questions
None.
Other
Failing runs: 30675870949 (
markdown_src_attributes, step "Log results"), 30675418090 (markdown_links, step "Check links against database"). Both fail with:Root cause: #12741 (shell-injection hardening) moved broken-link/broken-image JSON payloads, sometimes exceeding 200KB, into step-level
env:blocks.env:values are placed into the process environment table when the runnerexecve()s bash for the step. Linux caps individual argv/environ strings atMAX_ARG_STRLEN(128KB), so any payload larger than that crashes the spawn before the step body runs.Fix: replace each
env: VAR: ${{ steps.results.outputs.X }}+"$VAR"pattern in both workflow files withcat > file <<'DELIM' ... DELIM, writing the payload into the script body instead of the environment or argv. The heredoc delimiter is quoted, which disables parameter and command substitution on the body — untrusted$(...)or backtick content is written literally, never executed, so the injection protection from #12741 is preserved through a size-safe mechanism. Four call sites changed across the two workflow files..github/workflows/scripts/markdown_links/create_broken_link_issuesnow takes a file path as its first argument instead of an inline JSON string, since passing the payload as a literal argv element hits the same size limit.Second fix, same file:
markdown_src_attributes.yml's "Check status" step hadif: ${{ steps.results.outputs.status }} != 'success'— only the left-hand side is wrapped in${{ }}, so the whole expression evaluates to a non-empty literal string and is always truthy. The step therefore always ran and always failed, but this was masked by the "Log results" crash happening first. Corrected to${{ steps.results.outputs.status != 'success' }}, matching the form already used inmarkdown_links.yml.Validation: YAML syntax checked for both workflow files (
yaml.safe_load), bash syntax checked for the modified script (bash -n). Standalone reproduction confirmed the heredoc write produces byte-identical output to the oldecho "$VAR" >> fileapproach across compact JSON, pretty-printed JSON, empty string, empty array, and trailing-newline cases, and confirmed shell metacharacters,$(), and backticks embedded in a payload are written literally and never executed.Two residual items for maintainer attention, neither blocking:
stdlib-js/check-markdown-link-definitions-actionalways emits single-line JSON. That action is referenced via@mainrather than a pinned SHA — pre-existing, not introduced here, but worth a separate lookcreate_broken_link_issuesnow treats a genuinely empty failures file as "no broken links" (exit 0) instead of erroring; unreachable in the old code since the upstream action always emits at least[ ]for zero failuresChecklist
AI Assistance
If you answered "yes" above, how did you use AI assistance?
Disclosure
This PR was produced by an automated CI-maintenance routine. Root cause was identified via multi-agent investigation of the failing workflow runs, and the fix was independently validated by three separate reviewer agents (correctness, regression scope, style/conventions) before commit. A maintainer should still review before merging.
@stdlib-js/reviewers
Generated by Claude Code