◐ Shell
clean mode source ↗

Set timeout for CI by ShaharNaveh · Pull Request #5947 · RustPython/RustPython

🧩 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.