Add containerImageValidation experimental feature flag that gates the
new container image validation behind an opt-in toggle. When the flag
is off (default), the legacy converter logic is used. When enabled,
the improved validation with expression handling runs.
The legacy code is duplicated to keep code paths fully isolated and
make the eventual cleanup diff minimal — just delete the legacy
functions and the flag guards.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Related PR:
- https://github.com/actions/runner/pull/4220
Relaxing schema non-empty-string for container/service image and moving to custom validation. This matches current production behavior which allows empty string at runtime, but not parse time.
Update the step-uses description to mention that actions can also be
used from private repositories when access is enabled via repository
settings.
Fixes#319
## Problem
In workflow YAML files, writing `if: foo == bar` shows an error because `foo` and `bar` are not valid contexts. However, the same invalid expression in an action.yml file showed no error.
## Solution
Add expression validation for implicit `if` conditions in action.yml files, matching the behavior of workflow YAML validation.
## What's new
1. **Pre-if/post-if validation** (node and docker actions)
- `pre-if: foo == bar` now shows error for unknown context
- `post-if: unknownFunc()` now shows error for unknown function
2. **Composite step `if` validation** (fix)
- Errors from `convertToIfCondition` were being lost due to call ordering
- Now captured correctly by calling conversion before retrieving errors
## Why the refactor?
The diff includes consolidating multiple validation loops into a single `validateAllTokens()` traversal. This matches the pattern used in workflow YAML validation (`additionalValidations`), making the code consistent between the two validation paths.
* Add missing validation for action.yml (parity with workflow files)
- Add uses format validation for composite action steps
- Validates owner/repo@ref format
- Supports docker:// and ./ local references
- Warns about shortened SHA refs (security concern)
- Detects reusable workflow references in wrong context
- Add if literal text detection for composite action steps
- Detects literal text outside ${{ }} that makes conditions always truthy
- Works for both plain string and mixed expression formats
- Uses shared hasFormatWithLiteralText() utility
- Add pre-if/post-if validation for node and docker actions
- Errors on explicit ${{ }} syntax (runner only supports implicit expressions)
- Literal text detection for implicit expressions
- New runs-if schema type with proper context (runner, github, job, env, inputs, status functions)
- Validates only in strict schema used by language services
- Add format() function validation for all expressions
- Validates format string syntax in all expression contexts
- Checks argument count matches placeholders
- Fix env and matrix context providers to return complete=false
- Prevents false positive 'unknown context' errors
- Matches behavior of other dynamic contexts (secrets, vars, etc.)
- Refactor validation utilities into utils/validate-uses.ts and utils/validate-if.ts
- Shared between workflow and action validation
- Consistent error messages and codes
* Add strategy and matrix contexts to runs-if definition
Based on runner source code analysis (actions/runner):
- ExecutionContext.InitializeJob() populates ExpressionValues from message.ContextData
- strategy and matrix are part of message.ContextData, available before any steps run
- StepsRunner evaluates all steps (pre, main, post) using the same code path
Did NOT add:
- steps: empty at pre-if time (no steps completed yet)
- hashFiles: workspace files don't exist at pre-step time
In YAML, block scalars (`|` and `>`) silently add a trailing newline by default
("clip" chomping). This can cause subtle bugs when the newline is unintentional.
This PR adds a warning when clip chomping is used in fields where trailing
newlines commonly cause issues:
- Environment variables (workflow, job, step, container, service levels)
- Action inputs (`with:`)
- Reusable workflow inputs and secrets
- Job outputs
- Matrix values (including `include` and `exclude`)
- Concurrency groups
The warning suggests using `|-` (strip) or `|+` (keep) to be explicit.
Intentionally does NOT warn for:
- `run:` scripts (trailing newlines are normal)
- Fields trimmed server-side (`if:`, `name:`, `runs-on:`, etc.)
The feature is gated behind the `blockScalarChompingWarning` feature flag.
- Set main as required in node-runs-strict schema definition
- Add validation for invalid key combinations based on using value
- Add validation for missing required keys (main for node, steps for composite, image for docker)
- Filter autocomplete suggestions based on using value
- Prioritize 'using' in completions when not set yet
Fixes context-aware autocomplete for action.yml files where different
action types (node, composite, docker) have different valid keys under runs:
* Fix false positive for literal text in `if` conditions
Use token.value (parsed string without YAML quotes) instead of token.source
(raw YAML text) for expression parsing in single-line strings. This fixes a
false positive where `if: "${{ expr }}"` incorrectly triggered the
"literal text in condition" error because the outer quotes were treated as
literal text.
Follow-up to PR #216
Related issue: https://github.com/github/vscode-github-actions/issues/542
* Move issue reference to comment
Migrate expressions, workflow-parser, and languageservice packages to use
proper ESM imports with .js extensions that work with node16 moduleResolution.
Changes:
- Update tsconfig.build.json in each package to use module: node16 and
moduleResolution: node16
- Add .js extensions to all relative import paths (Option B approach)
- Fix yaml internal type imports in workflow-parser by defining local types
- Add skipLibCheck to handle @types/node compatibility issues
- Add TypeScript 5.8.3 override in root package.json
- Add ESM migration plan documentation
The languageserver package is deferred due to test hang issues that need
further investigation.
Related #154 - Upgrade moduleResolution from node to node16 or nodenext
Related #110 - Published ESM code has imports without file extensions
Related #64 - expressions: ERR_MODULE_NOT_FOUND attempting to run example
Related #146 - Can not import @actions/workflow-parser
Test results:
- expressions: 1068 tests passed
- workflow-parser: 292 tests passed
- languageservice: 452 tests passed
* docs: update ESM migration plan with findings
- Update languageserver blocker: vscode-languageserver v8.0.2 lacks ESM
exports (not a test hang issue)
- Document that Option B (manual .js extensions) was chosen over Option A
due to ts-jest compatibility issues
- Add workaround for yaml package internal types (LinePos, NodeBase)
- Update migration status table with accurate reason for deferral
- Add skipLibCheck note for @types/node compatibility
Fixes#51
Added the following activity types to pull_request and pull_request_target:
- milestoned
- demilestoned
- enqueued
- dequeued
These types were missing from workflow-v1.0.json but are valid workflow
triggers per GitHub docs.
Also added schema-sync.test.ts to ensure activity types in workflow-v1.0.json
stay in sync with webhooks.json. The test:
- Checks both directions (webhooks→schema and schema→webhooks)
- Has WEBHOOK_ONLY for types not valid as workflow triggers:
- check_suite: requested, rerequested
- registry_package: default
- Has SCHEMA_ONLY for types valid in workflows but not in webhooks:
- registry_package: updated
- Has NAME_MAPPINGS for naming differences:
- project_column: edited (webhook) ↔ updated (schema)
- Provides actionable error messages when mismatches are found
Fixes vscode#395 - Empty value for choice option shows 'Unexpected value' error
Empty strings are valid options for workflow_dispatch inputs with type: choice.
They allow users to make a choice 'optional' or force explicit selection.
Changes:
- Add sequence-of-string type that allows empty strings (unlike sequence-of-non-empty-string)
- Use sequence-of-string for workflow_dispatch options field
- Add test to verify empty string in choice options doesn't produce validation errors
Fixes https://github.com/github/vscode-github-actions/issues/405
YAML anchors (&name) and aliases (*name) are now properly supported.
When an alias is encountered during parsing, it is resolved to its
anchored value, making aliases transparent to the rest of the system.
Changes:
- workflow-parser: Handle isAlias nodes in YamlObjectReader.getNodes()
- languageservice: Add tests for various anchor/alias patterns
Test cases:
- Anchors in env mappings
- Multiple aliases to same anchor
- Anchors in matrix strategy
- Anchors in steps
- Scalar anchors (e.g., runs-on)
- Read allowed context from schema definition instead of hardcoded constants
- Parse expressions into AST to accurately detect status functions (avoids false positives from string literals)
- Export ensureStatusFunction helper that combines checking and wrapping logic
- Remove step-if.yml from skipped tests (now passes with accurate detection)
- Add tests for if-condition wrapping in hover/completion position mapping