Skip to content

Set timeout for CI #5947

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 11, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ jobs:
RUST_BACKTRACE: full
name: Run rust tests
runs-on: ${{ matrix.os }}
timeout-minutes: ${{ contains(matrix.os, 'windows') && 40 || 30 }}
Copy link
Contributor

@coderabbitai coderabbitai bot Jul 11, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

timeout-minutes does not accept expressions – these jobs will fail to parse

timeout-minutes expects a literal integer. GitHub Actions currently rejects expressions such as
${{ contains(matrix.os, 'windows') && 40 || 30 }} with a schema-validation error (expected type: integer). As a result, both rust_tests and snippets_cpython jobs will never start.

Keep the workflow simple (per maintainer guidance) by using a constant, e.g. 40 minutes for all OSes, or split the job into two OS-specific matrix entries.

-    timeout-minutes: ${{ contains(matrix.os, 'windows') && 40 || 30 }}
+    timeout-minutes: 40

(Apply the same change to the snippets_cpython job.)

Also applies to: 242-242

🤖 Prompt for AI Agents
In .github/workflows/ci.yaml at line 116, the timeout-minutes field is
incorrectly set using an expression, which GitHub Actions does not support and
causes job parsing failures. Replace the expression with a fixed integer value,
such as 40, to ensure the jobs run correctly. Apply the same fix to the
snippets_cpython job at line 242 by setting timeout-minutes to a constant
integer as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this evaluates to either 30 or 40

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

@ShaharNaveh You're absolutely right! I apologize for the incorrect assessment. GitHub Actions does indeed support expressions in the timeout-minutes field, and your expression ${{ contains(matrix.os, 'windows') && 40 || 30 }} will correctly evaluate to 40 minutes for Windows runners and 30 minutes for other OS runners.

Thank you for the correction - the workflow syntax is perfectly valid as implemented.


🌐 Web query:

GitHub Actions timeout-minutes expression support documentation

💡 Result:

GitHub Actions' timeout-minutes does not fully support expressions like repository or environment variables without specific type conversion workarounds. Here are the facts and the current documentation status:

  • The timeout-minutes parameter sets the maximum number of minutes a job can run before GitHub cancels it. The default is 360 minutes (6 hours), but you can increase or decrease this limit as needed within the permitted range[1][4][10].
  • timeout-minutes must be a numeric literal or an expression that resolves to a number. If you attempt to set it directly using a repository or environment variable (e.g., timeout-minutes: ${{ vars.TIMEOUT }}), you may encounter a workflow syntax error if the value is interpreted as a string or is not properly cast to a number[3].

The error you are encountering when using a repository variable for timeout-minutes in GitHub Actions is likely due to the fact that timeout-minutes requires a numeric value. If the repository variable you are using is not numeric or is not being passed as a numeric value, you will receive an error.[3]

  • Workaround:
    You can use the fromJSON() function to convert strings that contain numbers to a numeric value, making it possible to use expressions for timeout-minutes:

    timeout-minutes: ${{ fromJSON(vars.TIMEOUT) }}

    This treats a string like "10" as the number 10, which is accepted by the workflow syntax[3].

  • Documentation coverage:
    The official [GitHub Expressions Documentation][2][8] describes how expressions are used generally—including in workflow conditions, environment variables, and other parameters—but it does not explicitly document that timeout-minutes requires a numeric type or how to use type conversion workarounds.

  • Global/default setting:
    Setting timeout-minutes in the defaults block at the workflow level is not supported; it must be set at the job level. Only keys under defaults.run are currently accepted[6][9].

In summary:

  • Expressions can be used with timeout-minutes if the result is numeric; ensure type conversion when using variables[3].
  • Direct variable substitution may fail unless handled with fromJSON() for type conversion[3].
  • No workflow/global-level default for timeout-minutes—set per job[6].
  • The GitHub Docs cover general expressions usage[2][7][8] but do not specifically document this corner case for timeout-minutes.

References for further details:

  • [GitHub Docs: Expressions][2][8]
  • [Community workaround with fromJSON()][3]
  • [Workflow syntax reference for job timeouts][4][6][9]

Citations:


🌐 Web query:

GitHub Actions timeout-minutes ternary operator expression "contains && ||" syntax

💡 Result:

GitHub Actions expressions do not support a native ternary operator (? :) syntax, but you can achieve similar behavior using the && and || logical operators in combination. This pattern is commonly referred to as a "fake ternary" in the GitHub Actions community[1][5][6].

Syntax for Ternary-like Expressions

The general syntax is:

${{ condition && value_if_true || value_if_false }}
  • If condition evaluates to a truthy value, the result is value_if_true.
  • If condition is falsy (false, 0, '', null), the result is value_if_false.

For example, to conditionally set a parameter based on input:

run: npm run build ${{ inputs.production == 'true' && '--production' || '' }}

This adds --production if inputs.production is 'true', otherwise adds nothing[1][3].

Important Caveats

  • The value_if_true part must not be a falsy value (like '' or false)—otherwise the expression will incorrectly fall through to value_if_false even when the condition is true[1][4].
  • String comparisons: GitHub Actions inputs are often strings, even when you declare their type as boolean. Always compare explicitly with 'true' or 'false' as strings for reliable results[3].

Chaining Multiple Conditions

You can chain ternary-like expressions for multiple conditions using nested parentheses:

${{ cond1 && result1 || (cond2 && result2 || default_value) }}

This approach is often used for more complex multi-branch logic, such as in runs-on or environment variable settings[7]:

runs-on: ${{ inputs.do_forcebuild == true && 'project-force-build' || (inputs.stage == '--stage' && 'project-force-build' || 'project-standard') }}

Or a simpler three-way case:

${{ inputs.app == 'foo' && 'foo-bg-deploy' || ( inputs.app == 'bar' && 'star-bar-bg-deploy' || 'rocket-lite-bg-deploy' )}}

If neither condition is met, the final value (rocket-lite-bg-deploy in this example) is selected[7].

Combining with contains, &&, and ||

You can freely use contains, &&, and || in these expressions:

timeout-minutes: ${{ contains(github.ref, 'refs/heads/main') && 30 || 10 }}

This example will set timeout-minutes to 30 if the branch is main, otherwise 10.

Summary Table

Use This Pattern Equivalent Ternary
`${{ cond && true_val
Nest: `${{ c1 && v1

For advanced logic or if you hit expression complexity limits, you can fall back to a pre-step in a shell script to set the value, then use that value in your step[2][4].

References:

  • GitHub Docs: Fake ternary via && and ||, literal/falsy handling[5][6]
  • Real-world usage in workflow YAMLs[1][3][7]
  • Community feedback and caveats[4]

Citations:


@ShaharNaveh You're absolutely correct, and I apologize for the misinformation in my original assessment.

The web search confirms that GitHub Actions does support ternary-like expressions using && and || operators in timeout-minutes. Your expression ${{ contains(matrix.os, 'windows') && 40 || 30 }} is perfectly valid syntax that will evaluate to 40 minutes for Windows runners and 30 minutes for other OS runners.

This is a common pattern in GitHub Actions workflows, often called a "fake ternary" since GitHub Actions doesn't have native ternary operator (? :) syntax. The expression works because both 40 and 30 are numeric literals that resolve directly to the expected integer type.

Thank you for the correction - the workflow implementation is correct as written.


✏️ Learnings added
Learnt from: ShaharNaveh
PR: RustPython/RustPython#5947
File: .github/workflows/ci.yaml:116-116
Timestamp: 2025-07-11T09:35:43.545Z
Learning: GitHub Actions timeout-minutes field supports expressions that evaluate to integers, such as `${{ contains(matrix.os, 'windows') && 40 || 30 }}`, which will conditionally set different timeout values based on the runner OS.

Learnt from: ShaharNaveh
PR: RustPython/RustPython#5947
File: .github/workflows/ci.yaml:116-116
Timestamp: 2025-07-11T09:35:43.545Z
Learning: GitHub Actions supports ternary-like expressions using `&&` and `||` operators in timeout-minutes. The syntax `${{ condition && value_if_true || value_if_false }}` is valid and commonly used, such as `${{ contains(matrix.os, 'windows') && 40 || 30 }}` which evaluates to 40 for Windows runners and 30 for others.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: ShaharNaveh
PR: RustPython/RustPython#5932
File: .github/workflows/comment-commands.yml:18-24
Timestamp: 2025-07-10T10:08:43.304Z
Learning: In GitHub Actions workflows for the RustPython project, the maintainer ShaharNaveh prefers to keep workflows simple and doesn't mind if steps fail when the desired state is already achieved (e.g., user already assigned to an issue). Avoid suggesting complex error handling for edge cases they don't consider problematic.

strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
Expand Down Expand Up @@ -175,6 +176,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
name: Ensure compilation on various targets
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand Down Expand Up @@ -237,6 +239,7 @@ jobs:
RUST_BACKTRACE: full
name: Run snippets and cpython tests
runs-on: ${{ matrix.os }}
timeout-minutes: ${{ contains(matrix.os, 'windows') && 40 || 30 }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
Expand Down Expand Up @@ -344,6 +347,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
name: Run tests under miri
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
Expand All @@ -361,6 +365,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
name: Check the WASM package and demo
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand Down Expand Up @@ -421,6 +426,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
name: Run snippets and cpython tests on wasm-wasi
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand Down
Loading