fix(workflows): resolve negative list indices in expressions - #4416
Open
NgoQuocViet2001 wants to merge 1 commit into
Open
fix(workflows): resolve negative list indices in expressions#4416NgoQuocViet2001 wants to merge 1 commit into
NgoQuocViet2001 wants to merge 1 commit into
Conversation
_resolve_dot_path matched only digits in the index bracket, so `task_list[-1]` never entered the indexing branch. It fell through to the dict lookup and asked for the literal key "task_list[-1]", which returns None — a template reaching for the last element of a step output rendered empty with no error, and a condition on it silently read false. Accept the negative form Python and Jinja2 both use, and bound the index from both ends so out-of-range still yields None rather than raising.
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Condition-remediation parsing still rejects negative indices supported by the resolver.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds Python-style negative list indexing to workflow expressions.
Changes:
- Supports bounded negative indices.
- Adds resolution and bounds tests.
File summaries
| File | Description |
|---|---|
expressions.py |
Extends list-index parsing and bounds checks. |
test_workflows.py |
Tests negative and out-of-range indices. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # Handle list indexing: name[0] | ||
| idx_match = re.match(r"^([\w-]+)\[(\d+)\]$", part) | ||
| # Handle list indexing: name[0], name[-1] | ||
| idx_match = re.match(r"^([\w-]+)\[(-?\d+)\]$", part) |
mnriem
requested changes
Sep 3, 2026
mnriem
left a comment
Collaborator
There was a problem hiding this comment.
Please address Copilot feedback
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.
Problem
_resolve_dot_pathmatches the index bracket with^([\w-]+)\[(\d+)\]$, which accepts digits only. A negative index therefore never enters the indexing branch — it falls through to the dict lookup and asks for the literal key"task_list[-1]", which is absent, so the whole path resolves toNone:list[-1]is valid in both Python and the Jinja2 subset the module documents itself as providing, and "the last item a step produced" is a natural thing for a workflow template to want. There is no error: the template renders empty, andevaluate_conditionon the same path reads false, so a step can be skipped for a reason that never surfaces.Fix
Accept the negative form in the pattern and bound the index from both ends. Out-of-range in either direction keeps returning
Nonerather than raising, matching the existing behaviour for[9]on a short list.Scope
Two lines in
src/specify_cli/workflows/expressions.pyplus a docstring note, and one test next to the existingtest_list_indexing. Positive indices and non-index path segments are untouched.Test plan
pytest tests/test_workflows.py -k "indexing or literal"→ 11 passed.pytest tests/test_workflows.py→ 942 passed. The 20 failures are theTestWorkflowCliAlignmentsymlink cases, which fail identically on an unmodified checkout here (Windows, no symlink privilege).expressions.pyfails the new test withassert None == 'b.md'.