@actions/languageserver 0.3.34 → 0.3.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3267,7 +3267,7 @@ var require_main2 = __commonJS({
3267
3267
  ColorPresentation2.create = create;
3268
3268
  function is(value) {
3269
3269
  var candidate = value;
3270
- return Is.objectLiteral(candidate) && Is.string(candidate.label) && (Is.undefined(candidate.textEdit) || TextEdit2.is(candidate)) && (Is.undefined(candidate.additionalTextEdits) || Is.typedArray(candidate.additionalTextEdits, TextEdit2.is));
3270
+ return Is.objectLiteral(candidate) && Is.string(candidate.label) && (Is.undefined(candidate.textEdit) || TextEdit3.is(candidate)) && (Is.undefined(candidate.additionalTextEdits) || Is.typedArray(candidate.additionalTextEdits, TextEdit3.is));
3271
3271
  }
3272
3272
  ColorPresentation2.is = is;
3273
3273
  })(ColorPresentation = exports3.ColorPresentation || (exports3.ColorPresentation = {}));
@@ -3386,26 +3386,26 @@ var require_main2 = __commonJS({
3386
3386
  }
3387
3387
  Command2.is = is;
3388
3388
  })(Command = exports3.Command || (exports3.Command = {}));
3389
- var TextEdit2;
3390
- (function(TextEdit3) {
3389
+ var TextEdit3;
3390
+ (function(TextEdit4) {
3391
3391
  function replace(range, newText) {
3392
3392
  return { range, newText };
3393
3393
  }
3394
- TextEdit3.replace = replace;
3394
+ TextEdit4.replace = replace;
3395
3395
  function insert(position, newText) {
3396
3396
  return { range: { start: position, end: position }, newText };
3397
3397
  }
3398
- TextEdit3.insert = insert;
3398
+ TextEdit4.insert = insert;
3399
3399
  function del(range) {
3400
3400
  return { range, newText: "" };
3401
3401
  }
3402
- TextEdit3.del = del;
3402
+ TextEdit4.del = del;
3403
3403
  function is(value) {
3404
3404
  var candidate = value;
3405
3405
  return Is.objectLiteral(candidate) && Is.string(candidate.newText) && Range2.is(candidate.range);
3406
3406
  }
3407
- TextEdit3.is = is;
3408
- })(TextEdit2 = exports3.TextEdit || (exports3.TextEdit = {}));
3407
+ TextEdit4.is = is;
3408
+ })(TextEdit3 = exports3.TextEdit || (exports3.TextEdit = {}));
3409
3409
  var ChangeAnnotation;
3410
3410
  (function(ChangeAnnotation2) {
3411
3411
  function create(label, needsConfirmation, description) {
@@ -3449,7 +3449,7 @@ var require_main2 = __commonJS({
3449
3449
  AnnotatedTextEdit2.del = del;
3450
3450
  function is(value) {
3451
3451
  var candidate = value;
3452
- return TextEdit2.is(candidate) && (ChangeAnnotation.is(candidate.annotationId) || ChangeAnnotationIdentifier.is(candidate.annotationId));
3452
+ return TextEdit3.is(candidate) && (ChangeAnnotation.is(candidate.annotationId) || ChangeAnnotationIdentifier.is(candidate.annotationId));
3453
3453
  }
3454
3454
  AnnotatedTextEdit2.is = is;
3455
3455
  })(AnnotatedTextEdit = exports3.AnnotatedTextEdit || (exports3.AnnotatedTextEdit = {}));
@@ -3557,7 +3557,7 @@ var require_main2 = __commonJS({
3557
3557
  var edit;
3558
3558
  var id;
3559
3559
  if (annotation === void 0) {
3560
- edit = TextEdit2.insert(position, newText);
3560
+ edit = TextEdit3.insert(position, newText);
3561
3561
  } else if (ChangeAnnotationIdentifier.is(annotation)) {
3562
3562
  id = annotation;
3563
3563
  edit = AnnotatedTextEdit.insert(position, newText, annotation);
@@ -3575,7 +3575,7 @@ var require_main2 = __commonJS({
3575
3575
  var edit;
3576
3576
  var id;
3577
3577
  if (annotation === void 0) {
3578
- edit = TextEdit2.replace(range, newText);
3578
+ edit = TextEdit3.replace(range, newText);
3579
3579
  } else if (ChangeAnnotationIdentifier.is(annotation)) {
3580
3580
  id = annotation;
3581
3581
  edit = AnnotatedTextEdit.replace(range, newText, annotation);
@@ -3593,7 +3593,7 @@ var require_main2 = __commonJS({
3593
3593
  var edit;
3594
3594
  var id;
3595
3595
  if (annotation === void 0) {
3596
- edit = TextEdit2.del(range);
3596
+ edit = TextEdit3.del(range);
3597
3597
  } else if (ChangeAnnotationIdentifier.is(annotation)) {
3598
3598
  id = annotation;
3599
3599
  edit = AnnotatedTextEdit.del(range, annotation);
@@ -3901,39 +3901,39 @@ var require_main2 = __commonJS({
3901
3901
  }
3902
3902
  MarkupContent2.is = is;
3903
3903
  })(MarkupContent = exports3.MarkupContent || (exports3.MarkupContent = {}));
3904
- var CompletionItemKind2;
3905
- (function(CompletionItemKind3) {
3906
- CompletionItemKind3.Text = 1;
3907
- CompletionItemKind3.Method = 2;
3908
- CompletionItemKind3.Function = 3;
3909
- CompletionItemKind3.Constructor = 4;
3910
- CompletionItemKind3.Field = 5;
3911
- CompletionItemKind3.Variable = 6;
3912
- CompletionItemKind3.Class = 7;
3913
- CompletionItemKind3.Interface = 8;
3914
- CompletionItemKind3.Module = 9;
3915
- CompletionItemKind3.Property = 10;
3916
- CompletionItemKind3.Unit = 11;
3917
- CompletionItemKind3.Value = 12;
3918
- CompletionItemKind3.Enum = 13;
3919
- CompletionItemKind3.Keyword = 14;
3920
- CompletionItemKind3.Snippet = 15;
3921
- CompletionItemKind3.Color = 16;
3922
- CompletionItemKind3.File = 17;
3923
- CompletionItemKind3.Reference = 18;
3924
- CompletionItemKind3.Folder = 19;
3925
- CompletionItemKind3.EnumMember = 20;
3926
- CompletionItemKind3.Constant = 21;
3927
- CompletionItemKind3.Struct = 22;
3928
- CompletionItemKind3.Event = 23;
3929
- CompletionItemKind3.Operator = 24;
3930
- CompletionItemKind3.TypeParameter = 25;
3931
- })(CompletionItemKind2 = exports3.CompletionItemKind || (exports3.CompletionItemKind = {}));
3932
- var InsertTextFormat;
3933
- (function(InsertTextFormat2) {
3934
- InsertTextFormat2.PlainText = 1;
3935
- InsertTextFormat2.Snippet = 2;
3936
- })(InsertTextFormat = exports3.InsertTextFormat || (exports3.InsertTextFormat = {}));
3904
+ var CompletionItemKind3;
3905
+ (function(CompletionItemKind4) {
3906
+ CompletionItemKind4.Text = 1;
3907
+ CompletionItemKind4.Method = 2;
3908
+ CompletionItemKind4.Function = 3;
3909
+ CompletionItemKind4.Constructor = 4;
3910
+ CompletionItemKind4.Field = 5;
3911
+ CompletionItemKind4.Variable = 6;
3912
+ CompletionItemKind4.Class = 7;
3913
+ CompletionItemKind4.Interface = 8;
3914
+ CompletionItemKind4.Module = 9;
3915
+ CompletionItemKind4.Property = 10;
3916
+ CompletionItemKind4.Unit = 11;
3917
+ CompletionItemKind4.Value = 12;
3918
+ CompletionItemKind4.Enum = 13;
3919
+ CompletionItemKind4.Keyword = 14;
3920
+ CompletionItemKind4.Snippet = 15;
3921
+ CompletionItemKind4.Color = 16;
3922
+ CompletionItemKind4.File = 17;
3923
+ CompletionItemKind4.Reference = 18;
3924
+ CompletionItemKind4.Folder = 19;
3925
+ CompletionItemKind4.EnumMember = 20;
3926
+ CompletionItemKind4.Constant = 21;
3927
+ CompletionItemKind4.Struct = 22;
3928
+ CompletionItemKind4.Event = 23;
3929
+ CompletionItemKind4.Operator = 24;
3930
+ CompletionItemKind4.TypeParameter = 25;
3931
+ })(CompletionItemKind3 = exports3.CompletionItemKind || (exports3.CompletionItemKind = {}));
3932
+ var InsertTextFormat2;
3933
+ (function(InsertTextFormat3) {
3934
+ InsertTextFormat3.PlainText = 1;
3935
+ InsertTextFormat3.Snippet = 2;
3936
+ })(InsertTextFormat2 = exports3.InsertTextFormat || (exports3.InsertTextFormat = {}));
3937
3937
  var CompletionItemTag2;
3938
3938
  (function(CompletionItemTag3) {
3939
3939
  CompletionItemTag3.Deprecated = 1;
@@ -4359,7 +4359,7 @@ var require_main2 = __commonJS({
4359
4359
  InlayHint3.create = create;
4360
4360
  function is(value) {
4361
4361
  var candidate = value;
4362
- return Is.objectLiteral(candidate) && Position.is(candidate.position) && (Is.string(candidate.label) || Is.typedArray(candidate.label, InlayHintLabelPart.is)) && (candidate.kind === void 0 || InlayHintKind2.is(candidate.kind)) && candidate.textEdits === void 0 || Is.typedArray(candidate.textEdits, TextEdit2.is) && (candidate.tooltip === void 0 || Is.string(candidate.tooltip) || MarkupContent.is(candidate.tooltip)) && (candidate.paddingLeft === void 0 || Is.boolean(candidate.paddingLeft)) && (candidate.paddingRight === void 0 || Is.boolean(candidate.paddingRight));
4362
+ return Is.objectLiteral(candidate) && Position.is(candidate.position) && (Is.string(candidate.label) || Is.typedArray(candidate.label, InlayHintLabelPart.is)) && (candidate.kind === void 0 || InlayHintKind2.is(candidate.kind)) && candidate.textEdits === void 0 || Is.typedArray(candidate.textEdits, TextEdit3.is) && (candidate.tooltip === void 0 || Is.string(candidate.tooltip) || MarkupContent.is(candidate.tooltip)) && (candidate.paddingLeft === void 0 || Is.boolean(candidate.paddingLeft)) && (candidate.paddingRight === void 0 || Is.boolean(candidate.paddingRight));
4363
4363
  }
4364
4364
  InlayHint3.is = is;
4365
4365
  })(InlayHint2 = exports3.InlayHint || (exports3.InlayHint = {}));
@@ -19109,6 +19109,39 @@ var DescriptionDictionary = class extends Dictionary {
19109
19109
  }
19110
19110
  };
19111
19111
 
19112
+ // ../expressions/dist/features.js
19113
+ var allFeatureKeys = [
19114
+ "missingInputsQuickfix",
19115
+ "blockScalarChompingWarning",
19116
+ "actionScaffoldingSnippets"
19117
+ ];
19118
+ var FeatureFlags = class {
19119
+ constructor(features) {
19120
+ this.features = features ?? {};
19121
+ }
19122
+ /**
19123
+ * Check if an experimental feature is enabled.
19124
+ *
19125
+ * Resolution order:
19126
+ * 1. Explicit feature flag (if set)
19127
+ * 2. `all` flag (if set)
19128
+ * 3. false (default)
19129
+ */
19130
+ isEnabled(feature) {
19131
+ const explicit = this.features[feature];
19132
+ if (explicit !== void 0) {
19133
+ return explicit;
19134
+ }
19135
+ return this.features.all ?? false;
19136
+ }
19137
+ /**
19138
+ * Returns list of all enabled experimental features.
19139
+ */
19140
+ getEnabledFeatures() {
19141
+ return allFeatureKeys.filter((key) => this.isEnabled(key));
19142
+ }
19143
+ };
19144
+
19112
19145
  // ../workflow-parser/dist/templates/tokens/types.js
19113
19146
  var TokenType2;
19114
19147
  (function(TokenType3) {
@@ -19194,6 +19227,20 @@ var TraversalState = class {
19194
19227
  throw new Error(`Unexpected token type '${this._token.templateTokenType}' when traversing state`);
19195
19228
  }
19196
19229
  }
19230
+ /**
19231
+ * Returns the ancestor tokens from root to the current token's parent container.
19232
+ */
19233
+ getAncestors() {
19234
+ const ancestors = [];
19235
+ let state = this.parent;
19236
+ while (state) {
19237
+ if (state.current) {
19238
+ ancestors.unshift(state.current);
19239
+ }
19240
+ state = state.parent;
19241
+ }
19242
+ return ancestors;
19243
+ }
19197
19244
  };
19198
19245
 
19199
19246
  // ../workflow-parser/dist/templates/tokens/template-token.js
@@ -19299,11 +19346,12 @@ var TemplateToken = class {
19299
19346
  }
19300
19347
  /**
19301
19348
  * Returns all tokens (depth first)
19302
- * @param value The object to travese
19349
+ * @param value The object to traverse
19303
19350
  * @param omitKeys Whether to omit mapping keys
19351
+ * @yields A tuple of [parent, token, keyToken, ancestors] for each token in the tree
19304
19352
  */
19305
19353
  static *traverse(value, omitKeys) {
19306
- yield [void 0, value, void 0];
19354
+ yield [void 0, value, void 0, []];
19307
19355
  switch (value.templateTokenType) {
19308
19356
  case TokenType2.Sequence:
19309
19357
  case TokenType2.Mapping: {
@@ -19312,7 +19360,7 @@ var TemplateToken = class {
19312
19360
  while (state.parent) {
19313
19361
  if (state.moveNext(omitKeys ?? false)) {
19314
19362
  value = state.current;
19315
- yield [state.parent?.current, value, state.currentKey];
19363
+ yield [state.parent?.current, value, state.currentKey, state.getAncestors()];
19316
19364
  switch (value.type) {
19317
19365
  case TokenType2.Sequence:
19318
19366
  case TokenType2.Mapping:
@@ -19616,13 +19664,14 @@ var LiteralToken = class extends ScalarToken {
19616
19664
 
19617
19665
  // ../workflow-parser/dist/templates/tokens/string-token.js
19618
19666
  var StringToken = class _StringToken extends LiteralToken {
19619
- constructor(file, range, value, definitionInfo, source) {
19667
+ constructor(file, range, value, definitionInfo, source, blockScalarHeader) {
19620
19668
  super(TokenType2.String, file, range, definitionInfo);
19621
19669
  this.value = value;
19622
19670
  this.source = source;
19671
+ this.blockScalarHeader = blockScalarHeader;
19623
19672
  }
19624
19673
  clone(omitSource) {
19625
- return omitSource ? new _StringToken(void 0, void 0, this.value, this.definitionInfo, this.source) : new _StringToken(this.file, this.range, this.value, this.definitionInfo, this.source);
19674
+ return omitSource ? new _StringToken(void 0, void 0, this.value, this.definitionInfo, this.source, this.blockScalarHeader) : new _StringToken(this.file, this.range, this.value, this.definitionInfo, this.source, this.blockScalarHeader);
19626
19675
  }
19627
19676
  toString() {
19628
19677
  return this.value;
@@ -19848,20 +19897,28 @@ var ExpressionToken = class extends ScalarToken {
19848
19897
  // ../workflow-parser/dist/templates/tokens/basic-expression-token.js
19849
19898
  var BasicExpressionToken = class _BasicExpressionToken extends ExpressionToken {
19850
19899
  /**
19851
- * @param originalExpressions If the basic expression was transformed from individual expressions, these will be the original ones
19900
+ * @param file The file ID where this token originated
19901
+ * @param range The range of the entire expression including `${{` and `}}`
19902
+ * @param expression The expression string without `${{` and `}}` markers
19903
+ * @param definitionInfo Schema definition info for this token
19904
+ * @param originalExpressions If transformed from individual expressions (e.g., format()), these are the originals
19905
+ * @param source The original source string from the YAML
19906
+ * @param expressionRange The range of just the expression, excluding `${{` and `}}`
19907
+ * @param blockScalarHeader The block scalar header (e.g., "|", "|-") if parsed from a YAML block scalar
19852
19908
  */
19853
- constructor(file, range, expression, definitionInfo, originalExpressions, source, expressionRange) {
19909
+ constructor(file, range, expression, definitionInfo, originalExpressions, source, expressionRange, blockScalarHeader) {
19854
19910
  super(TokenType2.BasicExpression, file, range, void 0, definitionInfo);
19855
19911
  this.expr = expression;
19856
19912
  this.source = source;
19857
19913
  this.originalExpressions = originalExpressions;
19858
19914
  this.expressionRange = expressionRange;
19915
+ this.blockScalarHeader = blockScalarHeader;
19859
19916
  }
19860
19917
  get expression() {
19861
19918
  return this.expr;
19862
19919
  }
19863
19920
  clone(omitSource) {
19864
- return omitSource ? new _BasicExpressionToken(void 0, void 0, this.expr, this.definitionInfo, this.originalExpressions, this.source, this.expressionRange) : new _BasicExpressionToken(this.file, this.range, this.expr, this.definitionInfo, this.originalExpressions, this.source, this.expressionRange);
19921
+ return omitSource ? new _BasicExpressionToken(void 0, void 0, this.expr, this.definitionInfo, this.originalExpressions, this.source, this.expressionRange, this.blockScalarHeader) : new _BasicExpressionToken(this.file, this.range, this.expr, this.definitionInfo, this.originalExpressions, this.source, this.expressionRange, this.blockScalarHeader);
19865
19922
  }
19866
19923
  toString() {
19867
19924
  return `${OPEN_EXPRESSION} ${this.expr} ${CLOSE_EXPRESSION}`;
@@ -20270,7 +20327,7 @@ var TemplateReader = class {
20270
20327
  expressionTokens.push(expression);
20271
20328
  }
20272
20329
  }
20273
- return new BasicExpressionToken(this._fileId, token.range, `format('${format2.join("")}'${args.join("")})`, definitionInfo, expressionTokens, raw);
20330
+ return new BasicExpressionToken(this._fileId, token.range, `format('${format2.join("")}'${args.join("")})`, definitionInfo, expressionTokens, raw, void 0, token.blockScalarHeader);
20274
20331
  }
20275
20332
  parseIntoExpressionToken(tr, rawExpression, allowedContext, token, definitionInfo) {
20276
20333
  const parseExpressionResult = this.parseExpression(tr, token, rawExpression, allowedContext, definitionInfo);
@@ -20317,7 +20374,7 @@ var TemplateReader = class {
20317
20374
  }
20318
20375
  };
20319
20376
  return {
20320
- expression: new BasicExpressionToken(this._fileId, range, trimmed, definitionInfo, void 0, token.source, expressionRange),
20377
+ expression: new BasicExpressionToken(this._fileId, range, trimmed, definitionInfo, void 0, token.source, expressionRange, token.blockScalarHeader),
20321
20378
  error: void 0
20322
20379
  };
20323
20380
  }
@@ -21493,10 +21550,18 @@ var YamlObjectReader = class _YamlObjectReader {
21493
21550
  return new BooleanToken(fileId, range, value, void 0);
21494
21551
  case "string": {
21495
21552
  let source;
21553
+ let blockScalarHeader;
21496
21554
  if (token.srcToken && "source" in token.srcToken) {
21497
21555
  source = token.srcToken.source;
21556
+ if (token.srcToken.type === "block-scalar" && "props" in token.srcToken) {
21557
+ const props = token.srcToken.props;
21558
+ const headerProp = props.find((p) => p.type === "block-scalar-header");
21559
+ if (headerProp?.source) {
21560
+ blockScalarHeader = headerProp.source;
21561
+ }
21562
+ }
21498
21563
  }
21499
- return new StringToken(fileId, range, value, void 0, source);
21564
+ return new StringToken(fileId, range, value, void 0, source, blockScalarHeader);
21500
21565
  }
21501
21566
  default:
21502
21567
  throw new Error(`Unexpected value type '${typeof value}' when reading object`);
@@ -23066,7 +23131,7 @@ function getOptionsWithDefaults(options) {
23066
23131
  }
23067
23132
 
23068
23133
  // ../workflow-parser/dist/action-v1.0.min.json
23069
- var action_v1_0_min_default = { definitions: { "action-root": { description: "Action file", mapping: { properties: { name: "string", description: "string", inputs: "inputs", outputs: "outputs", runs: "runs" }, "loose-key-type": "non-empty-string", "loose-value-type": "any" } }, "action-root-strict": { description: "GitHub Action manifest file (action.yml/action.yaml) that defines an action's metadata, inputs, outputs, and execution configuration.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions)", mapping: { properties: { name: { type: "non-empty-string", required: true, description: "The name of your action. GitHub displays the name in the Actions tab to help visually identify actions in each job.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#name)" }, description: { type: "string", required: true, description: "A short description of the action. GitHub displays this description in the Actions Marketplace.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#description)" }, author: { type: "string", description: "The name of the action's author.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#author)" }, inputs: "inputs-strict", outputs: "outputs", runs: { type: "runs-strict", required: true }, branding: "branding" } } }, inputs: { mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "input" } }, "inputs-strict": { description: "Input parameters allow you to specify data that the action expects to use during runtime. GitHub stores input parameters as environment variables. Inputs ids with uppercase letters are converted to lowercase during runtime.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputs)", mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "input-strict" } }, input: { mapping: { properties: { default: "input-default-context" }, "loose-key-type": "non-empty-string", "loose-value-type": "any" } }, "input-strict": { description: "An input parameter for this action.", mapping: { properties: { description: { type: "string", description: "A string description of the input parameter.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_iddescription)" }, required: { type: "boolean", description: "A boolean to indicate whether the action requires the input parameter. Set to true when the parameter is required.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_idrequired)" }, default: { type: "input-default-context", description: "A string representing the default value. The default value is used when an input parameter isn't specified in a workflow file.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_iddefault)" }, deprecationMessage: { type: "string", description: "A string shown to users using the deprecated input, warning them that the input is deprecated and mentioning any alternatives.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_iddeprecationmessage)" } }, "loose-key-type": "non-empty-string", "loose-value-type": "any" } }, "input-default-context": { description: "A string representing the default value. The default value is used when an input parameter isn't specified in a workflow file.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_iddefault)", context: ["github", "strategy", "matrix", "job", "runner", "hashFiles(1,255)"], string: {} }, outputs: { description: "Output parameters allow you to declare data that an action sets. Actions that run later in a workflow can use the output data set in previously run actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#outputs-for-composite-actions)", mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "output-definition" } }, "output-definition": { description: "An output parameter for this action.", mapping: { properties: { description: { type: "string", description: "A string description of the output parameter.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#outputsoutput_iddescription)" }, value: { type: "output-value", description: "The value that the output parameter will be mapped to. You can set this to a string or an expression with context.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#outputsoutput_idvalue)" } } } }, "output-value": { description: "The value that the output parameter will be mapped to. You can set this to a string or an expression with context.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#outputsoutput_idvalue)", context: ["github", "strategy", "matrix", "steps", "inputs", "job", "runner", "env"], string: {} }, runs: { "one-of": ["container-runs", "node-runs", "composite-runs", "plugin-runs"] }, "runs-strict": { description: "Specifies whether this is a JavaScript action, a composite action, or a Docker container action and how the action is executed.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runs)", "one-of": ["container-runs-strict", "node-runs-strict", "composite-runs-strict"] }, "plugin-runs": { mapping: { properties: { plugin: "non-empty-string" } } }, "container-runs": { mapping: { properties: { using: "non-empty-string", image: "non-empty-string", entrypoint: "non-empty-string", args: "container-runs-args", env: "container-runs-env", "pre-entrypoint": "non-empty-string", "pre-if": "non-empty-string", "post-entrypoint": "non-empty-string", "post-if": "non-empty-string" } } }, "container-runs-args": { description: "An array of strings that define the inputs for a Docker container. Inputs can include hardcoded strings. GitHub passes the args to the container's ENTRYPOINT when the container starts up.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsargs)", sequence: { "item-type": "container-runs-context" } }, "container-runs-env": { description: "Specifies a key/value map of environment variables to set in the container environment.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsenv)", context: ["inputs"], mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "string" } }, "container-runs-context": { context: ["inputs"], string: {} }, "node-runs": { mapping: { properties: { using: "non-empty-string", main: "non-empty-string", pre: "non-empty-string", "pre-if": "non-empty-string", post: "non-empty-string", "post-if": "non-empty-string" } } }, "composite-runs": { mapping: { properties: { using: "non-empty-string", steps: "composite-steps" } } }, "container-runs-strict": { description: "Configuration for Docker container actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runs)", mapping: { properties: { using: { type: "using", required: true, description: "The runtime used to execute the action. Must be docker for Docker container actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsusing)" }, image: { type: "non-empty-string", required: true, description: "The Docker image to use as the container to run the action. The value can be the Docker base image name, a local Dockerfile in your repository, or a public image in Docker Hub or another registry.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsimage)" }, entrypoint: { type: "non-empty-string", description: "Overrides the Docker ENTRYPOINT in the Dockerfile, or sets it if one wasn't already specified.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsentrypoint)" }, args: "container-runs-args", env: "container-runs-env", "pre-entrypoint": { type: "non-empty-string", description: "Allows you to run a script before the entrypoint action begins.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspre-entrypoint)" }, "pre-if": { type: "non-empty-string", description: "Allows you to define conditions for the pre: action execution. The pre: action will only run if the conditions in pre-if are met. If not set, then pre-if defaults to always().\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspre-if)" }, "post-entrypoint": { type: "non-empty-string", description: "Allows you to run a cleanup script once the runs.entrypoint action has completed.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspost-entrypoint)" }, "post-if": { type: "non-empty-string", description: "Allows you to define conditions for the post: action execution. The post: action will only run if the conditions in post-if are met. If not set, then post-if defaults to always().\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspost-if)" } } } }, "node-runs-strict": { description: "Configuration for JavaScript actions executed with Node.js.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runs)", mapping: { properties: { using: { type: "using", required: true, description: "The runtime used to execute the action. Use node20 or node24 for JavaScript actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsusing)" }, main: { type: "non-empty-string", description: "The file that contains your action code. The runtime specified in using executes this file.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsmain)" }, pre: { type: "non-empty-string", description: "Allows you to run a script at the start of a job, before the main: action begins. You can use pre: to run prerequisite setup scripts.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspre)" }, "pre-if": { type: "non-empty-string", description: "Allows you to define conditions for the pre: action execution. The pre: action will only run if the conditions in pre-if are met. If not set, then pre-if defaults to always().\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspre-if)" }, post: { type: "non-empty-string", description: "Allows you to run a script at the end of a job, once the main: action has completed. You can use post: to run cleanup scripts.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspost)" }, "post-if": { type: "non-empty-string", description: "Allows you to define conditions for the post: action execution. The post: action will only run if the conditions in post-if are met. If not set, then post-if defaults to always().\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspost-if)" } } } }, "composite-runs-strict": { description: "Configuration for composite actions that run multiple steps.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runs)", mapping: { properties: { using: { type: "using", required: true, description: "The runtime used to execute the action. Must be composite for composite actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsusing)" }, steps: { type: "composite-steps", required: true } } } }, "composite-steps": { description: "The steps that you plan to run in this action. These can be either run steps or uses steps.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runssteps)", sequence: { "item-type": "composite-step" } }, "composite-step": { description: "A step within a composite action.", "one-of": ["run-step", "uses-step"] }, "run-step": { description: "Runs a command-line program using the operating system's shell.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsrun)", mapping: { properties: { name: { type: "string-steps-context", description: "A name for your step to display on GitHub.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsname)" }, id: { type: "non-empty-string", description: "A unique identifier for the step. You can use the id to reference the step in contexts.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsid)" }, if: { type: "step-if", description: "You can use the if conditional to prevent a step from running unless a condition is met. You can use any supported context and expression to create a conditional.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsif)" }, run: { type: "string-steps-context", required: true, description: "The command you want to run. This can be inline or a script in your action repository.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsrun)" }, shell: { type: "string-steps-context", required: true, description: "The shell where you want to run the command. Any shell supported by the runner can be used. Required if run is set.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsshell)" }, env: "step-env", "continue-on-error": { type: "boolean-steps-context", description: "Prevents the action from failing when a step fails. Set to true to allow the action to pass when this step fails.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepscontinue-on-error)" }, "working-directory": { type: "string-steps-context", description: "Specifies the working directory where the command is run.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsworking-directory)" } } } }, "uses-step": { description: "Runs another action as part of a step in your action.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsuses)", mapping: { properties: { name: { type: "string-steps-context", description: "A name for your step to display on GitHub.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsname)" }, id: { type: "non-empty-string", description: "A unique identifier for the step. You can use the id to reference the step in contexts.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsid)" }, if: { type: "step-if", description: "You can use the if conditional to prevent a step from running unless a condition is met. You can use any supported context and expression to create a conditional.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsif)" }, uses: { type: "non-empty-string", required: true, description: "Selects an action to run as part of a step in your action. An action is a reusable unit of code.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsuses)" }, with: "step-with", env: "step-env", "continue-on-error": { type: "boolean-steps-context", description: "Prevents the action from failing when a step fails. Set to true to allow the action to pass when this step fails.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepscontinue-on-error)" } } } }, "string-steps-context": { context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "hashFiles(1,255)"], string: {} }, "boolean-steps-context": { context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "hashFiles(1,255)"], boolean: {} }, "step-env": { description: "Sets variables for steps to use in the runner environment. You can also set variables for the entire action.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsenv)", context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "hashFiles(1,255)"], mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "string" } }, "step-if": { description: "You can use the if conditional to prevent a step from running unless a condition is met. You can use any supported context and expression to create a conditional.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsif)", context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "always(0,0)", "failure(0,0)", "cancelled(0,0)", "success(0,0)", "hashFiles(1,255)"], string: {} }, "step-with": { description: "A map of the input parameters defined by the action. Each input parameter is a key/value pair.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepswith)", context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "hashFiles(1,255)"], mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "string" } }, branding: { description: "You can use a color and Feather icon to create a badge to personalize and distinguish your action in GitHub Marketplace.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#branding)", mapping: { properties: { icon: { type: "branding-icon", description: "The name of the v4.28.0 Feather icon to use.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#brandingicon)" }, color: { type: "branding-color", description: "The background color of the badge.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#brandingcolor)" } } } }, "branding-icon": { description: "The name of the v4.28.0 Feather icon to use. Brand icons are omitted as well as: coffee, columns, divide-circle, divide-square, divide, frown, hexagon, key, meh, mouse-pointer, smile, tool, x-octagon.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#brandingicon)", "allowed-values": ["activity", "airplay", "alert-circle", "alert-octagon", "alert-triangle", "align-center", "align-justify", "align-left", "align-right", "anchor", "aperture", "archive", "arrow-down-circle", "arrow-down-left", "arrow-down-right", "arrow-down", "arrow-left-circle", "arrow-left", "arrow-right-circle", "arrow-right", "arrow-up-circle", "arrow-up-left", "arrow-up-right", "arrow-up", "at-sign", "award", "bar-chart-2", "bar-chart", "battery-charging", "battery", "bell-off", "bell", "bluetooth", "bold", "book-open", "book", "bookmark", "box", "briefcase", "calendar", "camera-off", "camera", "cast", "check-circle", "check-square", "check", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "chevrons-down", "chevrons-left", "chevrons-right", "chevrons-up", "circle", "clipboard", "clock", "cloud-drizzle", "cloud-lightning", "cloud-off", "cloud-rain", "cloud-snow", "cloud", "code", "command", "compass", "copy", "corner-down-left", "corner-down-right", "corner-left-down", "corner-left-up", "corner-right-down", "corner-right-up", "corner-up-left", "corner-up-right", "cpu", "credit-card", "crop", "crosshair", "database", "delete", "disc", "dollar-sign", "download-cloud", "download", "droplet", "edit-2", "edit-3", "edit", "external-link", "eye-off", "eye", "fast-forward", "feather", "file-minus", "file-plus", "file-text", "file", "film", "filter", "flag", "folder-minus", "folder-plus", "folder", "gift", "git-branch", "git-commit", "git-merge", "git-pull-request", "globe", "grid", "hard-drive", "hash", "headphones", "heart", "help-circle", "home", "image", "inbox", "info", "italic", "layers", "layout", "life-buoy", "link-2", "link", "list", "loader", "lock", "log-in", "log-out", "mail", "map-pin", "map", "maximize-2", "maximize", "menu", "message-circle", "message-square", "mic-off", "mic", "minimize-2", "minimize", "minus-circle", "minus-square", "minus", "monitor", "moon", "more-horizontal", "more-vertical", "move", "music", "navigation-2", "navigation", "octagon", "package", "paperclip", "pause-circle", "pause", "percent", "phone-call", "phone-forwarded", "phone-incoming", "phone-missed", "phone-off", "phone-outgoing", "phone", "pie-chart", "play-circle", "play", "plus-circle", "plus-square", "plus", "pocket", "power", "printer", "radio", "refresh-ccw", "refresh-cw", "repeat", "rewind", "rotate-ccw", "rotate-cw", "rss", "save", "scissors", "search", "send", "server", "settings", "share-2", "share", "shield-off", "shield", "shopping-bag", "shopping-cart", "shuffle", "sidebar", "skip-back", "skip-forward", "slash", "sliders", "smartphone", "speaker", "square", "star", "stop-circle", "sun", "sunrise", "sunset", "tablet", "tag", "target", "terminal", "thermometer", "thumbs-down", "thumbs-up", "toggle-left", "toggle-right", "trash-2", "trash", "trending-down", "trending-up", "triangle", "truck", "tv", "type", "umbrella", "underline", "unlock", "upload-cloud", "upload", "user-check", "user-minus", "user-plus", "user-x", "user", "users", "video-off", "video", "voicemail", "volume-1", "volume-2", "volume-x", "volume", "watch", "wifi-off", "wifi", "wind", "x-circle", "x-square", "x", "zap-off", "zap", "zoom-in", "zoom-out"] }, "branding-color": { description: "The background color of the badge.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#brandingcolor)", "allowed-values": ["white", "yellow", "blue", "green", "orange", "red", "purple", "gray-dark"] }, using: { description: "The runtime used to execute the action.", "allowed-values": ["docker", "node12", "node16", "node20", "node24", "composite"] }, "non-empty-string": { string: { "require-non-empty": true } } } };
23134
+ var action_v1_0_min_default = { definitions: { "action-root": { description: "Action file", mapping: { properties: { name: "string", description: "string", inputs: "inputs", outputs: "outputs", runs: "runs" }, "loose-key-type": "non-empty-string", "loose-value-type": "any" } }, "action-root-strict": { description: "GitHub Action manifest file (action.yml/action.yaml) that defines an action's metadata, inputs, outputs, and execution configuration.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions)", mapping: { properties: { name: { type: "non-empty-string", required: true, description: "The name of your action. GitHub displays the name in the Actions tab to help visually identify actions in each job.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#name)" }, description: { type: "string", required: true, description: "A short description of the action. GitHub displays this description in the Actions Marketplace.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#description)" }, author: { type: "string", description: "The name of the action's author.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#author)" }, inputs: "inputs-strict", outputs: "outputs", runs: { type: "runs-strict", required: true }, branding: "branding" } } }, inputs: { mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "input" } }, "inputs-strict": { description: "Input parameters allow you to specify data that the action expects to use during runtime. GitHub stores input parameters as environment variables. Inputs ids with uppercase letters are converted to lowercase during runtime.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputs)", mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "input-strict" } }, input: { mapping: { properties: { default: "input-default-context" }, "loose-key-type": "non-empty-string", "loose-value-type": "any" } }, "input-strict": { description: "An input parameter for this action.", mapping: { properties: { description: { type: "string", description: "A string description of the input parameter.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_iddescription)" }, required: { type: "boolean", description: "A boolean to indicate whether the action requires the input parameter. Set to true when the parameter is required.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_idrequired)" }, default: { type: "input-default-context", description: "A string representing the default value. The default value is used when an input parameter isn't specified in a workflow file.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_iddefault)" }, deprecationMessage: { type: "string", description: "A string shown to users using the deprecated input, warning them that the input is deprecated and mentioning any alternatives.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_iddeprecationmessage)" } }, "loose-key-type": "non-empty-string", "loose-value-type": "any" } }, "input-default-context": { description: "A string representing the default value. The default value is used when an input parameter isn't specified in a workflow file.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#inputsinput_iddefault)", context: ["github", "strategy", "matrix", "job", "runner", "hashFiles(1,255)"], string: {} }, outputs: { description: "Output parameters allow you to declare data that an action sets. Actions that run later in a workflow can use the output data set in previously run actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#outputs-for-composite-actions)", mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "output-definition" } }, "output-definition": { description: "An output parameter for this action.", mapping: { properties: { description: { type: "string", description: "A string description of the output parameter.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#outputsoutput_iddescription)" }, value: { type: "output-value", description: "The value that the output parameter will be mapped to. You can set this to a string or an expression with context.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#outputsoutput_idvalue)" } } } }, "output-value": { description: "The value that the output parameter will be mapped to. You can set this to a string or an expression with context.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#outputsoutput_idvalue)", context: ["github", "strategy", "matrix", "steps", "inputs", "job", "runner", "env"], string: {} }, runs: { "one-of": ["container-runs", "node-runs", "composite-runs", "plugin-runs"] }, "runs-strict": { description: "Specifies whether this is a JavaScript action, a composite action, or a Docker container action and how the action is executed.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runs)", "one-of": ["container-runs-strict", "node-runs-strict", "composite-runs-strict"] }, "plugin-runs": { mapping: { properties: { plugin: "non-empty-string" } } }, "container-runs": { mapping: { properties: { using: "non-empty-string", image: "non-empty-string", entrypoint: "non-empty-string", args: "container-runs-args", env: "container-runs-env", "pre-entrypoint": "non-empty-string", "pre-if": "non-empty-string", "post-entrypoint": "non-empty-string", "post-if": "non-empty-string" } } }, "container-runs-args": { description: "An array of strings that define the inputs for a Docker container. Inputs can include hardcoded strings. GitHub passes the args to the container's ENTRYPOINT when the container starts up.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsargs)", sequence: { "item-type": "container-runs-context" } }, "container-runs-env": { description: "Specifies a key/value map of environment variables to set in the container environment.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsenv)", context: ["inputs"], mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "string" } }, "container-runs-context": { context: ["inputs"], string: {} }, "node-runs": { mapping: { properties: { using: "non-empty-string", main: "non-empty-string", pre: "non-empty-string", "pre-if": "non-empty-string", post: "non-empty-string", "post-if": "non-empty-string" } } }, "composite-runs": { mapping: { properties: { using: "non-empty-string", steps: "composite-steps" } } }, "container-runs-strict": { description: "Configuration for Docker container actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runs)", mapping: { properties: { using: { type: "using", required: true, description: "The runtime used to execute the action. Must be docker for Docker container actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsusing)" }, image: { type: "non-empty-string", required: true, description: "The Docker image to use as the container to run the action. The value can be the Docker base image name, a local Dockerfile in your repository, or a public image in Docker Hub or another registry.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsimage)" }, entrypoint: { type: "non-empty-string", description: "Overrides the Docker ENTRYPOINT in the Dockerfile, or sets it if one wasn't already specified.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsentrypoint)" }, args: "container-runs-args", env: "container-runs-env", "pre-entrypoint": { type: "non-empty-string", description: "Allows you to run a script before the entrypoint action begins.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspre-entrypoint)" }, "pre-if": { type: "non-empty-string", description: "Allows you to define conditions for the pre: action execution. The pre: action will only run if the conditions in pre-if are met. If not set, then pre-if defaults to always().\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspre-if)" }, "post-entrypoint": { type: "non-empty-string", description: "Allows you to run a cleanup script once the runs.entrypoint action has completed.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspost-entrypoint)" }, "post-if": { type: "non-empty-string", description: "Allows you to define conditions for the post: action execution. The post: action will only run if the conditions in post-if are met. If not set, then post-if defaults to always().\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspost-if)" } } } }, "node-runs-strict": { description: "Configuration for JavaScript actions executed with Node.js.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runs)", mapping: { properties: { using: { type: "using", required: true, description: "The runtime used to execute the action. Use node20 or node24 for JavaScript actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsusing)" }, main: { type: "non-empty-string", required: true, description: "The file that contains your action code. The runtime specified in using executes this file.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsmain)" }, pre: { type: "non-empty-string", description: "Allows you to run a script at the start of a job, before the main: action begins. You can use pre: to run prerequisite setup scripts.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspre)" }, "pre-if": { type: "non-empty-string", description: "Allows you to define conditions for the pre: action execution. The pre: action will only run if the conditions in pre-if are met. If not set, then pre-if defaults to always().\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspre-if)" }, post: { type: "non-empty-string", description: "Allows you to run a script at the end of a job, once the main: action has completed. You can use post: to run cleanup scripts.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspost)" }, "post-if": { type: "non-empty-string", description: "Allows you to define conditions for the post: action execution. The post: action will only run if the conditions in post-if are met. If not set, then post-if defaults to always().\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runspost-if)" } } } }, "composite-runs-strict": { description: "Configuration for composite actions that run multiple steps.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runs)", mapping: { properties: { using: { type: "using", required: true, description: "The runtime used to execute the action. Must be composite for composite actions.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsusing)" }, steps: { type: "composite-steps", required: true } } } }, "composite-steps": { description: "The steps that you plan to run in this action. These can be either run steps or uses steps.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runssteps)", sequence: { "item-type": "composite-step" } }, "composite-step": { description: "A step within a composite action.", "one-of": ["run-step", "uses-step"] }, "run-step": { description: "Runs a command-line program using the operating system's shell.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsrun)", mapping: { properties: { name: { type: "string-steps-context", description: "A name for your step to display on GitHub.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsname)" }, id: { type: "non-empty-string", description: "A unique identifier for the step. You can use the id to reference the step in contexts.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsid)" }, if: { type: "step-if", description: "You can use the if conditional to prevent a step from running unless a condition is met. You can use any supported context and expression to create a conditional.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsif)" }, run: { type: "string-steps-context", required: true, description: "The command you want to run. This can be inline or a script in your action repository.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsrun)" }, shell: { type: "string-steps-context", required: true, description: "The shell where you want to run the command. Any shell supported by the runner can be used. Required if run is set.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsshell)" }, env: "step-env", "continue-on-error": { type: "boolean-steps-context", description: "Prevents the action from failing when a step fails. Set to true to allow the action to pass when this step fails.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepscontinue-on-error)" }, "working-directory": { type: "string-steps-context", description: "Specifies the working directory where the command is run.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsworking-directory)" } } } }, "uses-step": { description: "Runs another action as part of a step in your action.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsuses)", mapping: { properties: { name: { type: "string-steps-context", description: "A name for your step to display on GitHub.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsname)" }, id: { type: "non-empty-string", description: "A unique identifier for the step. You can use the id to reference the step in contexts.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsid)" }, if: { type: "step-if", description: "You can use the if conditional to prevent a step from running unless a condition is met. You can use any supported context and expression to create a conditional.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsif)" }, uses: { type: "non-empty-string", required: true, description: "Selects an action to run as part of a step in your action. An action is a reusable unit of code.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsuses)" }, with: "step-with", env: "step-env", "continue-on-error": { type: "boolean-steps-context", description: "Prevents the action from failing when a step fails. Set to true to allow the action to pass when this step fails.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepscontinue-on-error)" } } } }, "string-steps-context": { context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "hashFiles(1,255)"], string: {} }, "boolean-steps-context": { context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "hashFiles(1,255)"], boolean: {} }, "step-env": { description: "Sets variables for steps to use in the runner environment. You can also set variables for the entire action.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsenv)", context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "hashFiles(1,255)"], mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "string" } }, "step-if": { description: "You can use the if conditional to prevent a step from running unless a condition is met. You can use any supported context and expression to create a conditional.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsif)", context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "always(0,0)", "failure(0,0)", "cancelled(0,0)", "success(0,0)", "hashFiles(1,255)"], string: {} }, "step-with": { description: "A map of the input parameters defined by the action. Each input parameter is a key/value pair.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#runsstepswith)", context: ["github", "inputs", "strategy", "matrix", "steps", "job", "runner", "env", "hashFiles(1,255)"], mapping: { "loose-key-type": "non-empty-string", "loose-value-type": "string" } }, branding: { description: "You can use a color and Feather icon to create a badge to personalize and distinguish your action in GitHub Marketplace.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#branding)", mapping: { properties: { icon: { type: "branding-icon", description: "The name of the v4.28.0 Feather icon to use.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#brandingicon)" }, color: { type: "branding-color", description: "The background color of the badge.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#brandingcolor)" } } } }, "branding-icon": { description: "The name of the v4.28.0 Feather icon to use. Brand icons are omitted as well as: coffee, columns, divide-circle, divide-square, divide, frown, hexagon, key, meh, mouse-pointer, smile, tool, x-octagon.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#brandingicon)", "allowed-values": ["activity", "airplay", "alert-circle", "alert-octagon", "alert-triangle", "align-center", "align-justify", "align-left", "align-right", "anchor", "aperture", "archive", "arrow-down-circle", "arrow-down-left", "arrow-down-right", "arrow-down", "arrow-left-circle", "arrow-left", "arrow-right-circle", "arrow-right", "arrow-up-circle", "arrow-up-left", "arrow-up-right", "arrow-up", "at-sign", "award", "bar-chart-2", "bar-chart", "battery-charging", "battery", "bell-off", "bell", "bluetooth", "bold", "book-open", "book", "bookmark", "box", "briefcase", "calendar", "camera-off", "camera", "cast", "check-circle", "check-square", "check", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "chevrons-down", "chevrons-left", "chevrons-right", "chevrons-up", "circle", "clipboard", "clock", "cloud-drizzle", "cloud-lightning", "cloud-off", "cloud-rain", "cloud-snow", "cloud", "code", "command", "compass", "copy", "corner-down-left", "corner-down-right", "corner-left-down", "corner-left-up", "corner-right-down", "corner-right-up", "corner-up-left", "corner-up-right", "cpu", "credit-card", "crop", "crosshair", "database", "delete", "disc", "dollar-sign", "download-cloud", "download", "droplet", "edit-2", "edit-3", "edit", "external-link", "eye-off", "eye", "fast-forward", "feather", "file-minus", "file-plus", "file-text", "file", "film", "filter", "flag", "folder-minus", "folder-plus", "folder", "gift", "git-branch", "git-commit", "git-merge", "git-pull-request", "globe", "grid", "hard-drive", "hash", "headphones", "heart", "help-circle", "home", "image", "inbox", "info", "italic", "layers", "layout", "life-buoy", "link-2", "link", "list", "loader", "lock", "log-in", "log-out", "mail", "map-pin", "map", "maximize-2", "maximize", "menu", "message-circle", "message-square", "mic-off", "mic", "minimize-2", "minimize", "minus-circle", "minus-square", "minus", "monitor", "moon", "more-horizontal", "more-vertical", "move", "music", "navigation-2", "navigation", "octagon", "package", "paperclip", "pause-circle", "pause", "percent", "phone-call", "phone-forwarded", "phone-incoming", "phone-missed", "phone-off", "phone-outgoing", "phone", "pie-chart", "play-circle", "play", "plus-circle", "plus-square", "plus", "pocket", "power", "printer", "radio", "refresh-ccw", "refresh-cw", "repeat", "rewind", "rotate-ccw", "rotate-cw", "rss", "save", "scissors", "search", "send", "server", "settings", "share-2", "share", "shield-off", "shield", "shopping-bag", "shopping-cart", "shuffle", "sidebar", "skip-back", "skip-forward", "slash", "sliders", "smartphone", "speaker", "square", "star", "stop-circle", "sun", "sunrise", "sunset", "tablet", "tag", "target", "terminal", "thermometer", "thumbs-down", "thumbs-up", "toggle-left", "toggle-right", "trash-2", "trash", "trending-down", "trending-up", "triangle", "truck", "tv", "type", "umbrella", "underline", "unlock", "upload-cloud", "upload", "user-check", "user-minus", "user-plus", "user-x", "user", "users", "video-off", "video", "voicemail", "volume-1", "volume-2", "volume-x", "volume", "watch", "wifi-off", "wifi", "wind", "x-circle", "x-square", "x", "zap-off", "zap", "zoom-in", "zoom-out"] }, "branding-color": { description: "The background color of the badge.\n\n[Documentation](https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#brandingcolor)", "allowed-values": ["white", "yellow", "blue", "green", "orange", "red", "purple", "gray-dark"] }, using: { description: "The runtime used to execute the action.", "allowed-values": ["docker", "node12", "node16", "node20", "node24", "composite"] }, "non-empty-string": { string: { "require-non-empty": true } } } };
23070
23135
 
23071
23136
  // ../workflow-parser/dist/actions/action-schema.js
23072
23137
  var schema2;
@@ -23079,7 +23144,328 @@ function getActionSchema() {
23079
23144
  }
23080
23145
 
23081
23146
  // ../languageservice/dist/complete.js
23147
+ var import_vscode_languageserver_types2 = __toESM(require_main2(), 1);
23148
+
23149
+ // ../languageservice/dist/complete-action.js
23082
23150
  var import_vscode_languageserver_types = __toESM(require_main2(), 1);
23151
+ var ACTION_NODE_KEYS = /* @__PURE__ */ new Set(["using", "main", "pre", "post", "pre-if", "post-if"]);
23152
+ var ACTION_COMPOSITE_KEYS = /* @__PURE__ */ new Set(["using", "steps"]);
23153
+ var ACTION_DOCKER_KEYS = /* @__PURE__ */ new Set([
23154
+ "using",
23155
+ "image",
23156
+ "args",
23157
+ "env",
23158
+ "entrypoint",
23159
+ "pre-entrypoint",
23160
+ "pre-if",
23161
+ "post-entrypoint",
23162
+ "post-if"
23163
+ ]);
23164
+ var ACTION_SNIPPET_NODEJS_FULL = `name: '\${1:Action Name}'
23165
+ description: '\${2:What this action does}'
23166
+
23167
+ inputs:
23168
+ name:
23169
+ description: 'Name to greet'
23170
+ required: false
23171
+ default: 'World'
23172
+
23173
+ outputs:
23174
+ greeting:
23175
+ description: 'The greeting message'
23176
+
23177
+ runs:
23178
+ # For more on JavaScript actions (including @actions/toolkit), see:
23179
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-javascript-action
23180
+ using: node24
23181
+ main: index.js
23182
+ # Sample index.js (vanilla JS, no build required):
23183
+ #
23184
+ # const fs = require('fs');
23185
+ # const name = process.env.INPUT_NAME || 'World';
23186
+ # const greeting = \\\`Hello \\\${name}\\\`;
23187
+ # console.log(greeting);
23188
+ # fs.appendFileSync(process.env.GITHUB_OUTPUT, \\\`greeting=\\\${greeting}\\\\n\\\`);
23189
+ #
23190
+ # For JavaScript actions with @actions/toolkit, see:
23191
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-javascript-action
23192
+ `;
23193
+ var ACTION_SNIPPET_NODEJS_RUNS = `inputs:
23194
+ name:
23195
+ description: 'Name to greet'
23196
+ required: false
23197
+ default: 'World'
23198
+
23199
+ outputs:
23200
+ greeting:
23201
+ description: 'The greeting message'
23202
+
23203
+ runs:
23204
+ # For more on JavaScript actions (including @actions/toolkit), see:
23205
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-javascript-action
23206
+ using: node24
23207
+ main: index.js
23208
+ # Sample index.js (vanilla JS, no build required):
23209
+ #
23210
+ # const fs = require('fs');
23211
+ # const name = process.env.INPUT_NAME || 'World';
23212
+ # const greeting = \\\`Hello \\\${name}\\\`;
23213
+ # console.log(greeting);
23214
+ # fs.appendFileSync(process.env.GITHUB_OUTPUT, \\\`greeting=\\\${greeting}\\\\n\\\`);
23215
+ `;
23216
+ var ACTION_SNIPPET_NODEJS_USING = `# For more on JavaScript actions (including @actions/toolkit), see:
23217
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-javascript-action
23218
+ using: node24
23219
+ main: index.js
23220
+ # Sample index.js (vanilla JS, no build required):
23221
+ #
23222
+ # console.log('Hello World');
23223
+ `;
23224
+ var ACTION_SNIPPET_COMPOSITE_FULL = `name: '\${1:Action Name}'
23225
+ description: '\${2:What this action does}'
23226
+
23227
+ inputs:
23228
+ name:
23229
+ description: 'Name to greet'
23230
+ required: false
23231
+ default: 'World'
23232
+
23233
+ outputs:
23234
+ greeting:
23235
+ description: 'The greeting message'
23236
+ value: \\\${{ steps.greet.outputs.greeting }}
23237
+
23238
+ runs:
23239
+ # For more on composite actions, see:
23240
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action
23241
+ using: composite
23242
+ steps:
23243
+ - id: greet
23244
+ shell: bash
23245
+ env:
23246
+ INPUT_NAME: \\\${{ inputs.name }}
23247
+ run: |
23248
+ GREETING="Hello $INPUT_NAME"
23249
+ echo "$GREETING"
23250
+ echo "greeting=$GREETING" >> $GITHUB_OUTPUT
23251
+ `;
23252
+ var ACTION_SNIPPET_COMPOSITE_RUNS = `inputs:
23253
+ name:
23254
+ description: 'Name to greet'
23255
+ required: false
23256
+ default: 'World'
23257
+
23258
+ outputs:
23259
+ greeting:
23260
+ description: 'The greeting message'
23261
+ value: \\\${{ steps.greet.outputs.greeting }}
23262
+
23263
+ runs:
23264
+ # For more on composite actions, see:
23265
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action
23266
+ using: composite
23267
+ steps:
23268
+ - id: greet
23269
+ shell: bash
23270
+ env:
23271
+ INPUT_NAME: \\\${{ inputs.name }}
23272
+ run: |
23273
+ GREETING="Hello $INPUT_NAME"
23274
+ echo "$GREETING"
23275
+ echo "greeting=$GREETING" >> $GITHUB_OUTPUT
23276
+ `;
23277
+ var ACTION_SNIPPET_COMPOSITE_USING = `# For more on composite actions, see:
23278
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action
23279
+ using: composite
23280
+ steps:
23281
+ - shell: bash
23282
+ run: echo "Hello World"
23283
+ `;
23284
+ var ACTION_SNIPPET_DOCKER_FULL = `name: '\${1:Action Name}'
23285
+ description: '\${2:What this action does}'
23286
+
23287
+ inputs:
23288
+ name:
23289
+ description: 'Name to greet'
23290
+ required: false
23291
+ default: 'World'
23292
+
23293
+ outputs:
23294
+ greeting:
23295
+ description: 'The greeting message'
23296
+
23297
+ runs:
23298
+ # For more on Docker actions, see:
23299
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-docker-container-action
23300
+ using: docker
23301
+ # 'docker://image:tag' uses pre-built image, 'Dockerfile' builds locally
23302
+ image: '\${3:docker://alpine:3.20}'
23303
+ env:
23304
+ INPUT_NAME: \\\${{ inputs.name }}
23305
+ entrypoint: '\${4:sh}'
23306
+ args:
23307
+ - -c
23308
+ - |
23309
+ GREETING="Hello $INPUT_NAME"
23310
+ echo "$GREETING"
23311
+ echo "greeting=$GREETING" >> $GITHUB_OUTPUT
23312
+ `;
23313
+ var ACTION_SNIPPET_DOCKER_RUNS = `inputs:
23314
+ name:
23315
+ description: 'Name to greet'
23316
+ required: false
23317
+ default: 'World'
23318
+
23319
+ outputs:
23320
+ greeting:
23321
+ description: 'The greeting message'
23322
+
23323
+ runs:
23324
+ # For more on Docker actions, see:
23325
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-docker-container-action
23326
+ using: docker
23327
+ # 'docker://image:tag' uses pre-built image, 'Dockerfile' builds locally
23328
+ image: '\${1:docker://alpine:3.20}'
23329
+ env:
23330
+ INPUT_NAME: \\\${{ inputs.name }}
23331
+ entrypoint: '\${2:sh}'
23332
+ args:
23333
+ - -c
23334
+ - |
23335
+ GREETING="Hello $INPUT_NAME"
23336
+ echo "$GREETING"
23337
+ echo "greeting=$GREETING" >> $GITHUB_OUTPUT
23338
+ `;
23339
+ var ACTION_SNIPPET_DOCKER_USING = `# For more on Docker actions, see:
23340
+ # https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-docker-container-action
23341
+ using: docker
23342
+ # 'docker://image:tag' uses pre-built image, 'Dockerfile' builds locally
23343
+ image: '\${1:docker://alpine:3.20}'
23344
+ entrypoint: '\${2:sh}'
23345
+ args:
23346
+ - -c
23347
+ - echo "Hello World"
23348
+ `;
23349
+ function filterActionRunsCompletions(values, path, root) {
23350
+ let runsMapping;
23351
+ if (root instanceof MappingToken) {
23352
+ for (let i = 0; i < root.count; i++) {
23353
+ const { key, value } = root.get(i);
23354
+ if (key.toString().toLowerCase() === "runs" && value instanceof MappingToken) {
23355
+ runsMapping = value;
23356
+ break;
23357
+ }
23358
+ }
23359
+ }
23360
+ if (!runsMapping) {
23361
+ return values;
23362
+ }
23363
+ const isInsideRuns = path.some((token) => token === runsMapping);
23364
+ if (!isInsideRuns) {
23365
+ return values;
23366
+ }
23367
+ const runsMappingIndex = path.indexOf(runsMapping);
23368
+ if (runsMappingIndex === -1) {
23369
+ return values;
23370
+ }
23371
+ if (runsMappingIndex < path.length - 1) {
23372
+ return values;
23373
+ }
23374
+ let usingValue;
23375
+ for (let i = 0; i < runsMapping.count; i++) {
23376
+ const { key, value } = runsMapping.get(i);
23377
+ if (key.toString().toLowerCase() === "using") {
23378
+ usingValue = value.toString();
23379
+ break;
23380
+ }
23381
+ }
23382
+ let allowedKeys;
23383
+ if (!usingValue) {
23384
+ return values.map((v) => {
23385
+ if (v.label.toLowerCase() === "using") {
23386
+ return { ...v, sortText: "0_using" };
23387
+ }
23388
+ return v;
23389
+ });
23390
+ } else if (usingValue.match(/^node\d+$/i)) {
23391
+ allowedKeys = ACTION_NODE_KEYS;
23392
+ } else if (usingValue.toLowerCase() === "composite") {
23393
+ allowedKeys = ACTION_COMPOSITE_KEYS;
23394
+ } else if (usingValue.toLowerCase() === "docker") {
23395
+ allowedKeys = ACTION_DOCKER_KEYS;
23396
+ } else {
23397
+ return values;
23398
+ }
23399
+ return values.filter((v) => allowedKeys.has(v.label.toLowerCase()));
23400
+ }
23401
+ function getActionScaffoldingSnippets(root, path, position) {
23402
+ let runsMapping;
23403
+ if (root instanceof MappingToken) {
23404
+ for (let i = 0; i < root.count; i++) {
23405
+ const { key, value } = root.get(i);
23406
+ if (key.toString().toLowerCase() === "runs" && value instanceof MappingToken) {
23407
+ runsMapping = value;
23408
+ break;
23409
+ }
23410
+ }
23411
+ }
23412
+ if (runsMapping) {
23413
+ for (let i = 0; i < runsMapping.count; i++) {
23414
+ const { key } = runsMapping.get(i);
23415
+ if (key.toString().toLowerCase() === "using") {
23416
+ return [];
23417
+ }
23418
+ }
23419
+ }
23420
+ const runsMappingIndex = runsMapping ? path.indexOf(runsMapping) : -1;
23421
+ const isDirectlyInsideRuns = runsMappingIndex !== -1 && runsMappingIndex === path.length - 1;
23422
+ if (isDirectlyInsideRuns) {
23423
+ return [
23424
+ createSnippetCompletion("Node.js Action", "Scaffold a Node.js action", ACTION_SNIPPET_NODEJS_USING, position, "1_nodejs"),
23425
+ createSnippetCompletion("Composite Action", "Scaffold a composite action", ACTION_SNIPPET_COMPOSITE_USING, position, "2_composite"),
23426
+ createSnippetCompletion("Docker Action", "Scaffold a Docker action", ACTION_SNIPPET_DOCKER_USING, position, "3_docker")
23427
+ ];
23428
+ }
23429
+ const isAtRoot = path.length === 0 || path.length === 1 && path[0] === root;
23430
+ if (!isAtRoot || runsMapping) {
23431
+ return [];
23432
+ }
23433
+ let hasNameOrDescription = false;
23434
+ if (root instanceof MappingToken) {
23435
+ for (let i = 0; i < root.count; i++) {
23436
+ const keyStr = root.get(i).key.toString().toLowerCase();
23437
+ if (keyStr === "name" || keyStr === "description") {
23438
+ hasNameOrDescription = true;
23439
+ break;
23440
+ }
23441
+ }
23442
+ }
23443
+ if (hasNameOrDescription) {
23444
+ return [
23445
+ createSnippetCompletion("Node.js Action", "Scaffold a Node.js action", ACTION_SNIPPET_NODEJS_RUNS, position, "1_nodejs"),
23446
+ createSnippetCompletion("Composite Action", "Scaffold a composite action", ACTION_SNIPPET_COMPOSITE_RUNS, position, "2_composite"),
23447
+ createSnippetCompletion("Docker Action", "Scaffold a Docker action", ACTION_SNIPPET_DOCKER_RUNS, position, "3_docker")
23448
+ ];
23449
+ }
23450
+ return [
23451
+ createSnippetCompletion("Node.js Action", "Scaffold a complete Node.js action", ACTION_SNIPPET_NODEJS_FULL, position, "1_nodejs"),
23452
+ createSnippetCompletion("Composite Action", "Scaffold a complete composite action", ACTION_SNIPPET_COMPOSITE_FULL, position, "2_composite"),
23453
+ createSnippetCompletion("Docker Action", "Scaffold a complete Docker action", ACTION_SNIPPET_DOCKER_FULL, position, "3_docker")
23454
+ ];
23455
+ }
23456
+ function createSnippetCompletion(label, description, snippetText, position, sortText) {
23457
+ return {
23458
+ label,
23459
+ kind: import_vscode_languageserver_types.CompletionItemKind.Snippet,
23460
+ documentation: {
23461
+ kind: "markdown",
23462
+ value: description
23463
+ },
23464
+ insertTextFormat: import_vscode_languageserver_types.InsertTextFormat.Snippet,
23465
+ sortText,
23466
+ textEdit: import_vscode_languageserver_types.TextEdit.insert(position, snippetText)
23467
+ };
23468
+ }
23083
23469
 
23084
23470
  // ../languageservice/dist/context/action-context.js
23085
23471
  function getActionContext(uri, template, tokenPath) {
@@ -25188,9 +25574,16 @@ async function complete2(textDocument, position, config) {
25188
25574
  }
25189
25575
  const indentation = guessIndentation(newDoc, 2, true);
25190
25576
  const indentString = " ".repeat(indentation.tabSize);
25191
- const values = await getValues(token, keyToken, parent, config?.valueProviderConfig, workflowContext, indentString, schema3);
25577
+ let values = await getValues(token, keyToken, parent, config?.valueProviderConfig, workflowContext, indentString, schema3);
25578
+ if (isAction && parsedTemplate.value) {
25579
+ values = filterActionRunsCompletions(values, path, parsedTemplate.value);
25580
+ }
25192
25581
  const escapeHatches = getEscapeHatchCompletions(token, keyToken, indentString, newPos, schema3);
25193
25582
  values.push(...escapeHatches);
25583
+ let actionSnippets = [];
25584
+ if (isAction && config?.featureFlags?.isEnabled("actionScaffoldingSnippets")) {
25585
+ actionSnippets = getActionScaffoldingSnippets(parsedTemplate.value, path, position);
25586
+ }
25194
25587
  let replaceRange;
25195
25588
  if (token?.range) {
25196
25589
  replaceRange = mapRange(token.range);
@@ -25202,24 +25595,24 @@ async function complete2(textDocument, position, config) {
25202
25595
  end: { line: position.line, character: position.character + 1 }
25203
25596
  });
25204
25597
  if (charAfterPos === ":") {
25205
- replaceRange = import_vscode_languageserver_types.Range.create({ line: position.line, character: position.character - val }, { line: position.line, character: position.character + 1 });
25598
+ replaceRange = import_vscode_languageserver_types2.Range.create({ line: position.line, character: position.character - val }, { line: position.line, character: position.character + 1 });
25206
25599
  } else {
25207
- replaceRange = import_vscode_languageserver_types.Range.create({ line: position.line, character: position.character - val }, position);
25600
+ replaceRange = import_vscode_languageserver_types2.Range.create({ line: position.line, character: position.character - val }, position);
25208
25601
  }
25209
25602
  }
25210
- return values.map((value) => {
25603
+ const completionItems = values.map((value) => {
25211
25604
  const newText = value.insertText || value.label;
25212
25605
  let textEdit;
25213
25606
  if (value.textEdit) {
25214
- textEdit = import_vscode_languageserver_types.TextEdit.replace(value.textEdit.range, value.textEdit.newText);
25607
+ textEdit = import_vscode_languageserver_types2.TextEdit.replace(value.textEdit.range, value.textEdit.newText);
25215
25608
  } else if (replaceRange) {
25216
- textEdit = import_vscode_languageserver_types.TextEdit.replace(replaceRange, newText);
25609
+ textEdit = import_vscode_languageserver_types2.TextEdit.replace(replaceRange, newText);
25217
25610
  } else {
25218
- textEdit = import_vscode_languageserver_types.TextEdit.insert(position, newText);
25611
+ textEdit = import_vscode_languageserver_types2.TextEdit.insert(position, newText);
25219
25612
  }
25220
25613
  let additionalTextEdits;
25221
25614
  if (value.additionalTextEdits) {
25222
- additionalTextEdits = value.additionalTextEdits.map((edit) => import_vscode_languageserver_types.TextEdit.replace(edit.range, edit.newText));
25615
+ additionalTextEdits = value.additionalTextEdits.map((edit) => import_vscode_languageserver_types2.TextEdit.replace(edit.range, edit.newText));
25223
25616
  }
25224
25617
  const item = {
25225
25618
  label: value.label,
@@ -25230,12 +25623,13 @@ async function complete2(textDocument, position, config) {
25230
25623
  kind: "markdown",
25231
25624
  value: value.description
25232
25625
  },
25233
- tags: value.deprecated ? [import_vscode_languageserver_types.CompletionItemTag.Deprecated] : void 0,
25626
+ tags: value.deprecated ? [import_vscode_languageserver_types2.CompletionItemTag.Deprecated] : void 0,
25234
25627
  textEdit,
25235
25628
  additionalTextEdits
25236
25629
  };
25237
25630
  return item;
25238
25631
  });
25632
+ return [...completionItems, ...actionSnippets];
25239
25633
  }
25240
25634
  async function getValues(token, keyToken, parent, valueProviderConfig, workflowContext, indentation, schema3) {
25241
25635
  if (!parent) {
@@ -25440,7 +25834,7 @@ function mapExpressionCompletionItem(item, charAfterPos) {
25440
25834
  value: item.description
25441
25835
  },
25442
25836
  insertText,
25443
- kind: item.function ? import_vscode_languageserver_types.CompletionItemKind.Function : import_vscode_languageserver_types.CompletionItemKind.Variable
25837
+ kind: item.function ? import_vscode_languageserver_types2.CompletionItemKind.Function : import_vscode_languageserver_types2.CompletionItemKind.Variable
25444
25838
  };
25445
25839
  }
25446
25840
  function getOffsetInContent(tokenRange, currentInput, pos) {
@@ -26148,6 +26542,15 @@ async function hover(document, position, config) {
26148
26542
  return null;
26149
26543
  }
26150
26544
  info(`Calculating hover for token with definition ${hoverToken.definition.key}`);
26545
+ if (isString(hoverToken) && hoverToken.definition.key === "cron-pattern") {
26546
+ const cronDescription = getCronDescription(hoverToken.value);
26547
+ if (cronDescription) {
26548
+ return {
26549
+ contents: cronDescription,
26550
+ range: mapRange(hoverToken.range)
26551
+ };
26552
+ }
26553
+ }
26151
26554
  let description;
26152
26555
  if (!isAction && tokenResult.parent && isReusableWorkflowJobInput(tokenResult)) {
26153
26556
  description = getReusableWorkflowInputDescription(documentContext, tokenResult);
@@ -26225,7 +26628,7 @@ function expressionHover(exprPos, expressionContext, namedContexts, functions) {
26225
26628
  }
26226
26629
 
26227
26630
  // ../languageservice/dist/inlay-hints.js
26228
- var import_vscode_languageserver_types2 = __toESM(require_main2(), 1);
26631
+ var import_vscode_languageserver_types3 = __toESM(require_main2(), 1);
26229
26632
  function getInlayHints(document) {
26230
26633
  if (isActionDocument(document.uri)) {
26231
26634
  return [];
@@ -26253,7 +26656,7 @@ function getInlayHints(document) {
26253
26656
  // Convert from 1-based to 0-based
26254
26657
  },
26255
26658
  label: `\u2192 ${description}`,
26256
- kind: import_vscode_languageserver_types2.InlayHintKind.Parameter,
26659
+ kind: import_vscode_languageserver_types3.InlayHintKind.Parameter,
26257
26660
  paddingLeft: true
26258
26661
  });
26259
26662
  }
@@ -26263,7 +26666,7 @@ function getInlayHints(document) {
26263
26666
  }
26264
26667
 
26265
26668
  // ../languageservice/dist/validate.js
26266
- var import_vscode_languageserver_types5 = __toESM(require_main2(), 1);
26669
+ var import_vscode_languageserver_types6 = __toESM(require_main2(), 1);
26267
26670
 
26268
26671
  // ../languageservice/dist/expression-validation/error-dictionary.js
26269
26672
  var AccessError = class extends Error {
@@ -26342,7 +26745,7 @@ var ValidationEvaluator = class extends Evaluator {
26342
26745
  };
26343
26746
 
26344
26747
  // ../languageservice/dist/validate-action-reference.js
26345
- var import_vscode_languageserver_types3 = __toESM(require_main2(), 1);
26748
+ var import_vscode_languageserver_types4 = __toESM(require_main2(), 1);
26346
26749
  async function validateActionReference(diagnostics, stepToken, step, config) {
26347
26750
  if (!isMapping(stepToken) || !step || !isActionStep(step) || !config?.actionsMetadataProvider) {
26348
26751
  return;
@@ -26354,7 +26757,7 @@ async function validateActionReference(diagnostics, stepToken, step, config) {
26354
26757
  const actionMetadata = await config.actionsMetadataProvider.fetchActionMetadata(action);
26355
26758
  if (actionMetadata === void 0) {
26356
26759
  diagnostics.push({
26357
- severity: import_vscode_languageserver_types3.DiagnosticSeverity.Error,
26760
+ severity: import_vscode_languageserver_types4.DiagnosticSeverity.Error,
26358
26761
  range: mapRange(step.uses.range),
26359
26762
  message: `Unable to resolve action \`${step.uses.value}\`, repository or version not found`
26360
26763
  });
@@ -26382,7 +26785,7 @@ async function validateActionReference(diagnostics, stepToken, step, config) {
26382
26785
  for (const [input, inputToken] of stepInputs) {
26383
26786
  if (!actionInputs[input]) {
26384
26787
  diagnostics.push({
26385
- severity: import_vscode_languageserver_types3.DiagnosticSeverity.Error,
26788
+ severity: import_vscode_languageserver_types4.DiagnosticSeverity.Error,
26386
26789
  range: mapRange(inputToken.range),
26387
26790
  message: `Invalid action input '${input}'`
26388
26791
  });
@@ -26390,7 +26793,7 @@ async function validateActionReference(diagnostics, stepToken, step, config) {
26390
26793
  const deprecationMessage = actionInputs[input]?.deprecationMessage;
26391
26794
  if (deprecationMessage) {
26392
26795
  diagnostics.push({
26393
- severity: import_vscode_languageserver_types3.DiagnosticSeverity.Warning,
26796
+ severity: import_vscode_languageserver_types4.DiagnosticSeverity.Warning,
26394
26797
  range: mapRange(inputToken.range),
26395
26798
  message: deprecationMessage
26396
26799
  });
@@ -26400,7 +26803,7 @@ async function validateActionReference(diagnostics, stepToken, step, config) {
26400
26803
  if (missingRequiredInputs.length > 0) {
26401
26804
  const message = missingRequiredInputs.length === 1 ? `Missing required input \`${missingRequiredInputs[0][0]}\`` : `Missing required inputs: ${missingRequiredInputs.map((input) => `\`${input[0]}\``).join(", ")}`;
26402
26805
  diagnostics.push({
26403
- severity: import_vscode_languageserver_types3.DiagnosticSeverity.Error,
26806
+ severity: import_vscode_languageserver_types4.DiagnosticSeverity.Error,
26404
26807
  range: mapRange((withKey || stepToken).range),
26405
26808
  message
26406
26809
  });
@@ -26408,7 +26811,23 @@ async function validateActionReference(diagnostics, stepToken, step, config) {
26408
26811
  }
26409
26812
 
26410
26813
  // ../languageservice/dist/validate-action.js
26411
- var import_vscode_languageserver_types4 = __toESM(require_main2(), 1);
26814
+ var import_vscode_languageserver_types5 = __toESM(require_main2(), 1);
26815
+ var NODE_KEYS = /* @__PURE__ */ new Set(["using", "main", "pre", "post", "pre-if", "post-if"]);
26816
+ var COMPOSITE_KEYS = /* @__PURE__ */ new Set(["using", "steps"]);
26817
+ var DOCKER_KEYS = /* @__PURE__ */ new Set([
26818
+ "using",
26819
+ "image",
26820
+ "args",
26821
+ "env",
26822
+ "entrypoint",
26823
+ "pre-entrypoint",
26824
+ "pre-if",
26825
+ "post-entrypoint",
26826
+ "post-if"
26827
+ ]);
26828
+ var NODE_REQUIRED_KEYS = ["main"];
26829
+ var COMPOSITE_REQUIRED_KEYS = ["steps"];
26830
+ var DOCKER_REQUIRED_KEYS = ["image"];
26412
26831
  async function validateAction(textDocument, config) {
26413
26832
  const file = {
26414
26833
  name: textDocument.uri,
@@ -26420,11 +26839,15 @@ async function validateAction(textDocument, config) {
26420
26839
  if (!result) {
26421
26840
  return [];
26422
26841
  }
26423
- for (const err of result.context.errors.getErrors()) {
26842
+ const schemaErrors = result.context.errors.getErrors();
26843
+ if (result.value) {
26844
+ diagnostics.push(...validateRunsKeysAndFilterErrors(result.value, schemaErrors));
26845
+ }
26846
+ for (const err of schemaErrors) {
26424
26847
  const range = mapRange(err.range);
26425
- let severity = import_vscode_languageserver_types4.DiagnosticSeverity.Error;
26848
+ let severity = import_vscode_languageserver_types5.DiagnosticSeverity.Error;
26426
26849
  if (err.rawMessage.includes("deprecated")) {
26427
- severity = import_vscode_languageserver_types4.DiagnosticSeverity.Warning;
26850
+ severity = import_vscode_languageserver_types5.DiagnosticSeverity.Warning;
26428
26851
  }
26429
26852
  diagnostics.push({
26430
26853
  message: err.rawMessage,
@@ -26463,6 +26886,222 @@ function findStepsSequence(root) {
26463
26886
  }
26464
26887
  return void 0;
26465
26888
  }
26889
+ function validateRunsKeysAndFilterErrors(root, schemaErrors) {
26890
+ const diagnostics = [];
26891
+ let runsMapping;
26892
+ if (root instanceof MappingToken) {
26893
+ for (let i = 0; i < root.count; i++) {
26894
+ const { key, value } = root.get(i);
26895
+ if (key.toString().toLowerCase() === "runs" && value instanceof MappingToken) {
26896
+ runsMapping = value;
26897
+ break;
26898
+ }
26899
+ }
26900
+ }
26901
+ if (!runsMapping) {
26902
+ return diagnostics;
26903
+ }
26904
+ let usingValue;
26905
+ for (let i = 0; i < runsMapping.count; i++) {
26906
+ const { key, value } = runsMapping.get(i);
26907
+ if (key.toString().toLowerCase() === "using") {
26908
+ usingValue = value.toString();
26909
+ break;
26910
+ }
26911
+ }
26912
+ if (!usingValue) {
26913
+ return diagnostics;
26914
+ }
26915
+ let allowedKeys;
26916
+ let requiredKeys;
26917
+ let actionType;
26918
+ if (usingValue.match(/^node\d+$/i)) {
26919
+ allowedKeys = NODE_KEYS;
26920
+ requiredKeys = NODE_REQUIRED_KEYS;
26921
+ actionType = "Node.js";
26922
+ } else if (usingValue.toLowerCase() === "composite") {
26923
+ allowedKeys = COMPOSITE_KEYS;
26924
+ requiredKeys = COMPOSITE_REQUIRED_KEYS;
26925
+ actionType = "composite";
26926
+ } else if (usingValue.toLowerCase() === "docker") {
26927
+ allowedKeys = DOCKER_KEYS;
26928
+ requiredKeys = DOCKER_REQUIRED_KEYS;
26929
+ actionType = "Docker";
26930
+ } else {
26931
+ return diagnostics;
26932
+ }
26933
+ const presentKeys = /* @__PURE__ */ new Set();
26934
+ for (let i = 0; i < runsMapping.count; i++) {
26935
+ const { key } = runsMapping.get(i);
26936
+ presentKeys.add(key.toString().toLowerCase());
26937
+ }
26938
+ for (let i = 0; i < runsMapping.count; i++) {
26939
+ const { key } = runsMapping.get(i);
26940
+ const keyStr = key.toString().toLowerCase();
26941
+ if (!allowedKeys.has(keyStr)) {
26942
+ diagnostics.push({
26943
+ severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error,
26944
+ range: mapRange(key.range),
26945
+ message: `'${key.toString()}' is not valid for ${actionType} actions (using: ${usingValue})`
26946
+ });
26947
+ }
26948
+ }
26949
+ for (const requiredKey of requiredKeys) {
26950
+ if (!presentKeys.has(requiredKey)) {
26951
+ let usingKeyRange = runsMapping.range;
26952
+ for (let i = 0; i < runsMapping.count; i++) {
26953
+ const { key } = runsMapping.get(i);
26954
+ if (key.toString().toLowerCase() === "using") {
26955
+ usingKeyRange = key.range;
26956
+ break;
26957
+ }
26958
+ }
26959
+ diagnostics.push({
26960
+ severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error,
26961
+ range: mapRange(usingKeyRange),
26962
+ message: `'${requiredKey}' is required for ${actionType} actions (using: ${usingValue})`
26963
+ });
26964
+ }
26965
+ }
26966
+ for (let i = schemaErrors.length - 1; i >= 0; i--) {
26967
+ const err = schemaErrors[i];
26968
+ if (err.range?.start.line !== runsMapping.range?.start.line || err.range?.start.column !== runsMapping.range?.start.column) {
26969
+ continue;
26970
+ }
26971
+ const isOneOfAmbiguity = err.rawMessage.startsWith("There's not enough info to determine");
26972
+ const isRequiredKey = /^Required property is missing: (main|steps|image)$/.test(err.rawMessage);
26973
+ if (!isOneOfAmbiguity && !isRequiredKey) {
26974
+ continue;
26975
+ }
26976
+ if (diagnostics.length > 0) {
26977
+ schemaErrors.splice(i, 1);
26978
+ }
26979
+ }
26980
+ return diagnostics;
26981
+ }
26982
+
26983
+ // ../languageservice/dist/validate-format-string.js
26984
+ function validateFormatString(formatString) {
26985
+ let maxIndex = -1;
26986
+ let i = 0;
26987
+ while (i < formatString.length) {
26988
+ let lbrace = -1;
26989
+ for (let j = i; j < formatString.length; j++) {
26990
+ if (formatString[j] === "{") {
26991
+ lbrace = j;
26992
+ break;
26993
+ }
26994
+ }
26995
+ let rbrace = -1;
26996
+ for (let j = i; j < formatString.length; j++) {
26997
+ if (formatString[j] === "}") {
26998
+ rbrace = j;
26999
+ break;
27000
+ }
27001
+ }
27002
+ if (lbrace < 0 && rbrace < 0) {
27003
+ break;
27004
+ }
27005
+ if (lbrace >= 0 && (rbrace < 0 || lbrace < rbrace)) {
27006
+ if (lbrace + 1 < formatString.length && formatString[lbrace + 1] === "{") {
27007
+ i = lbrace + 2;
27008
+ continue;
27009
+ }
27010
+ rbrace = -1;
27011
+ for (let j = lbrace + 1; j < formatString.length; j++) {
27012
+ if (formatString[j] === "}") {
27013
+ rbrace = j;
27014
+ break;
27015
+ }
27016
+ }
27017
+ if (rbrace < 0) {
27018
+ return { valid: false, maxArgIndex: -1 };
27019
+ }
27020
+ if (rbrace === lbrace + 1) {
27021
+ return { valid: false, maxArgIndex: -1 };
27022
+ }
27023
+ let index = 0;
27024
+ for (let j = lbrace + 1; j < rbrace; j++) {
27025
+ const c = formatString[j];
27026
+ if (c < "0" || c > "9") {
27027
+ return { valid: false, maxArgIndex: -1 };
27028
+ }
27029
+ index = index * 10 + (c.charCodeAt(0) - "0".charCodeAt(0));
27030
+ }
27031
+ if (index > maxIndex) {
27032
+ maxIndex = index;
27033
+ }
27034
+ i = rbrace + 1;
27035
+ continue;
27036
+ }
27037
+ if (rbrace + 1 < formatString.length && formatString[rbrace + 1] === "}") {
27038
+ i = rbrace + 2;
27039
+ continue;
27040
+ }
27041
+ return { valid: false, maxArgIndex: -1 };
27042
+ }
27043
+ return { valid: true, maxArgIndex: maxIndex };
27044
+ }
27045
+ function validateFormatCalls(expr) {
27046
+ const errors = [];
27047
+ const stack = [expr];
27048
+ while (stack.length > 0) {
27049
+ const node = stack.pop();
27050
+ if (!node) {
27051
+ continue;
27052
+ }
27053
+ if (node instanceof FunctionCall) {
27054
+ if (node.functionName.lexeme.toLowerCase() === "format") {
27055
+ const error2 = validateSingleFormatCall(node);
27056
+ if (error2) {
27057
+ errors.push(error2);
27058
+ }
27059
+ }
27060
+ for (const arg of node.args) {
27061
+ stack.push(arg);
27062
+ }
27063
+ } else if (node instanceof Binary) {
27064
+ stack.push(node.left, node.right);
27065
+ } else if (node instanceof Unary) {
27066
+ stack.push(node.expr);
27067
+ } else if (node instanceof Logical) {
27068
+ for (const arg of node.args) {
27069
+ stack.push(arg);
27070
+ }
27071
+ } else if (node instanceof Grouping) {
27072
+ stack.push(node.group);
27073
+ } else if (node instanceof IndexAccess) {
27074
+ stack.push(node.expr, node.index);
27075
+ }
27076
+ }
27077
+ return errors;
27078
+ }
27079
+ function validateSingleFormatCall(fc) {
27080
+ if (fc.args.length < 1) {
27081
+ return void 0;
27082
+ }
27083
+ const firstArg = fc.args[0];
27084
+ if (!(firstArg instanceof Literal) || firstArg.literal.kind !== Kind.String) {
27085
+ return void 0;
27086
+ }
27087
+ const formatString = firstArg.literal.coerceString();
27088
+ const numArgs = fc.args.length - 1;
27089
+ const { valid, maxArgIndex } = validateFormatString(formatString);
27090
+ if (!valid) {
27091
+ return {
27092
+ type: "invalid-syntax",
27093
+ message: "Format string has invalid syntax (missing closing brace, unescaped braces, or invalid placeholder)"
27094
+ };
27095
+ }
27096
+ if (maxArgIndex >= numArgs) {
27097
+ return {
27098
+ type: "arg-count-mismatch",
27099
+ expected: maxArgIndex + 1,
27100
+ provided: numArgs
27101
+ };
27102
+ }
27103
+ return void 0;
27104
+ }
26466
27105
 
26467
27106
  // ../languageservice/dist/validate.js
26468
27107
  var CRON_SCHEDULE_DOCS_URL = "https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#onschedule";
@@ -26485,7 +27124,7 @@ async function validateWorkflow(textDocument, config) {
26485
27124
  fetchReusableWorkflowDepth: config?.fileProvider ? 1 : 0,
26486
27125
  errorPolicy: ErrorPolicy.TryConversion
26487
27126
  });
26488
- await additionalValidations(diagnostics, textDocument.uri, template, result.value, config);
27127
+ await additionalValidations(diagnostics, textDocument.uri, template, result.value, config, config?.featureFlags);
26489
27128
  }
26490
27129
  for (const error2 of result.context.errors.getErrors()) {
26491
27130
  const range = mapRange(error2.range);
@@ -26499,19 +27138,22 @@ async function validateWorkflow(textDocument, config) {
26499
27138
  }
26500
27139
  return diagnostics;
26501
27140
  }
26502
- async function additionalValidations(diagnostics, documentUri, template, root, config) {
26503
- for (const [parent, token, key] of TemplateToken.traverse(root)) {
27141
+ async function additionalValidations(diagnostics, documentUri, template, root, config, featureFlags) {
27142
+ for (const [parent, token, key, ancestors] of TemplateToken.traverse(root)) {
26504
27143
  const validationToken = key || parent || token;
26505
27144
  const validationDefinition = validationToken.definition;
26506
27145
  if (isBasicExpression(token) && token.range) {
26507
27146
  await validateExpression(diagnostics, token, validationToken.definitionInfo?.allowedContext || [], config?.contextProviderConfig, getProviderContext(documentUri, template, root, token.range), key?.definition?.key);
26508
27147
  }
27148
+ if (featureFlags?.isEnabled("blockScalarChompingWarning")) {
27149
+ validateBlockScalarChomping(diagnostics, token, parent, key, ancestors);
27150
+ }
26509
27151
  const definitionKey = token.definition?.key;
26510
27152
  if (isString(token) && token.range && (definitionKey === "job-if" || definitionKey === "step-if" || definitionKey === "snapshot-if")) {
26511
27153
  const condition = token.value.trim();
26512
27154
  if (condition) {
26513
27155
  const finalCondition = ensureStatusFunction(condition, token.definitionInfo);
26514
- const expressionToken = new BasicExpressionToken(token.file, token.range, finalCondition, token.definitionInfo, void 0, token.source);
27156
+ const expressionToken = new BasicExpressionToken(token.file, token.range, finalCondition, token.definitionInfo, void 0, token.source, void 0, token.blockScalarHeader);
26515
27157
  await validateExpression(diagnostics, expressionToken, validationToken.definitionInfo?.allowedContext || [], config?.contextProviderConfig, getProviderContext(documentUri, template, root, token.range));
26516
27158
  }
26517
27159
  }
@@ -26559,7 +27201,7 @@ function invalidValue(diagnostics, token, kind) {
26559
27201
  case ValueProviderKind.AllowedValues:
26560
27202
  diagnostics.push({
26561
27203
  message: `Value '${token.value}' is not valid`,
26562
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error,
27204
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
26563
27205
  range: mapRange(token.range)
26564
27206
  });
26565
27207
  break;
@@ -26578,7 +27220,7 @@ function validateCronExpression(diagnostics, token) {
26578
27220
  diagnostics.push({
26579
27221
  message: `Actions schedules run at most every 5 minutes. "${cronValue}" (${description.toLowerCase()}) will not run as frequently as specified.`,
26580
27222
  range: mapRange(token.range),
26581
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Warning,
27223
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Warning,
26582
27224
  code: "on-schedule",
26583
27225
  codeDescription: {
26584
27226
  href: CRON_SCHEDULE_DOCS_URL
@@ -26592,7 +27234,7 @@ function warnIfShortSha(diagnostics, token, ref) {
26592
27234
  if (SHORT_SHA_PATTERN.test(ref)) {
26593
27235
  diagnostics.push({
26594
27236
  message: `The provided ref '${ref}' may be a shortened commit SHA. If so, please use the full 40-character commit SHA instead, as short SHAs are not supported.`,
26595
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Warning,
27237
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Warning,
26596
27238
  range: mapRange(token.range),
26597
27239
  code: "short-sha-ref",
26598
27240
  codeDescription: {
@@ -26608,7 +27250,7 @@ function validateStepUsesFormat(diagnostics, token) {
26608
27250
  if (!uses) {
26609
27251
  diagnostics.push({
26610
27252
  message: "`uses' value in action cannot be blank",
26611
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error,
27253
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
26612
27254
  range: mapRange(token.range),
26613
27255
  code: "invalid-uses-format"
26614
27256
  });
@@ -26638,7 +27280,7 @@ function validateStepUsesFormat(diagnostics, token) {
26638
27280
  if (pathSegments.length >= 4 && pathSegments[2] === ".github" && pathSegments[3] === "workflows") {
26639
27281
  diagnostics.push({
26640
27282
  message: "Reusable workflows should be referenced at the top-level `jobs.<job_id>.uses` key, not within steps",
26641
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error,
27283
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
26642
27284
  range: mapRange(token.range),
26643
27285
  code: "invalid-uses-format"
26644
27286
  });
@@ -26649,7 +27291,7 @@ function validateStepUsesFormat(diagnostics, token) {
26649
27291
  function addStepUsesFormatError(diagnostics, token) {
26650
27292
  diagnostics.push({
26651
27293
  message: `Expected format {owner}/{repo}[/path]@{ref}. Actual '${token.value}'`,
26652
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error,
27294
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
26653
27295
  range: mapRange(token.range),
26654
27296
  code: "invalid-uses-format"
26655
27297
  });
@@ -26738,7 +27380,7 @@ function validateWorkflowUsesFormat(diagnostics, token) {
26738
27380
  function addWorkflowUsesFormatError(diagnostics, token, reason) {
26739
27381
  diagnostics.push({
26740
27382
  message: `Invalid workflow reference '${token.value}': ${reason}`,
26741
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error,
27383
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
26742
27384
  range: mapRange(token.range),
26743
27385
  code: "invalid-workflow-uses-format"
26744
27386
  });
@@ -26834,7 +27476,7 @@ async function validateExpression(diagnostics, token, allowedContext, contextPro
26834
27476
  diagnostics.push({
26835
27477
  message: "Conditional expression contains literal text outside replacement tokens. This will cause the expression to always evaluate to truthy. Did you mean to put the entire expression inside ${{ }}?",
26836
27478
  range: mapRange(token.range),
26837
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error,
27479
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
26838
27480
  code: "expression-literal-text-in-condition"
26839
27481
  });
26840
27482
  }
@@ -26851,13 +27493,31 @@ async function validateExpression(diagnostics, token, allowedContext, contextPro
26851
27493
  } catch {
26852
27494
  continue;
26853
27495
  }
27496
+ const formatErrors = validateFormatCalls(expr);
27497
+ for (const formatError of formatErrors) {
27498
+ if (formatError.type === "invalid-syntax") {
27499
+ diagnostics.push({
27500
+ message: `Invalid format string: ${formatError.message}`,
27501
+ range: mapRange(expression.range),
27502
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
27503
+ code: "invalid-format-string"
27504
+ });
27505
+ } else if (formatError.type === "arg-count-mismatch") {
27506
+ diagnostics.push({
27507
+ message: `Format string references argument {${formatError.expected - 1}} but only ${formatError.provided} argument(s) provided`,
27508
+ range: mapRange(expression.range),
27509
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error,
27510
+ code: "format-arg-count-mismatch"
27511
+ });
27512
+ }
27513
+ }
26854
27514
  const context = await getWorkflowExpressionContext(namedContexts, contextProviderConfig, workflowContext, Mode.Validation);
26855
27515
  const e = new ValidationEvaluator(expr, wrapDictionary(context), validatorFunctions);
26856
27516
  e.validate();
26857
27517
  diagnostics.push(...e.errors.map((e2) => ({
26858
27518
  message: e2.message,
26859
27519
  range: mapRange(expression.range),
26860
- severity: e2.severity === "error" ? import_vscode_languageserver_types5.DiagnosticSeverity.Error : import_vscode_languageserver_types5.DiagnosticSeverity.Warning
27520
+ severity: e2.severity === "error" ? import_vscode_languageserver_types6.DiagnosticSeverity.Error : import_vscode_languageserver_types6.DiagnosticSeverity.Warning
26861
27521
  })));
26862
27522
  }
26863
27523
  }
@@ -26879,14 +27539,14 @@ function validateConcurrencyDeadlock(diagnostics, template) {
26879
27539
  diagnostics.push({
26880
27540
  message: `Concurrency group '${workflowGroup.value}' is also used by job '${job.id.value}'. This will cause a deadlock.`,
26881
27541
  range: mapRange(template.concurrency.range),
26882
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error
27542
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error
26883
27543
  });
26884
27544
  }
26885
27545
  if (job.concurrency.range) {
26886
27546
  diagnostics.push({
26887
27547
  message: `Concurrency group '${jobGroup.value}' is also defined at the workflow level. This will cause a deadlock.`,
26888
27548
  range: mapRange(job.concurrency.range),
26889
- severity: import_vscode_languageserver_types5.DiagnosticSeverity.Error
27549
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Error
26890
27550
  });
26891
27551
  }
26892
27552
  }
@@ -26908,6 +27568,53 @@ function getStaticConcurrencyGroup(token) {
26908
27568
  }
26909
27569
  return void 0;
26910
27570
  }
27571
+ function validateBlockScalarChomping(diagnostics, token, parent, key, ancestors) {
27572
+ if (!isBasicExpression(token) && !isString(token)) {
27573
+ return;
27574
+ }
27575
+ const header = token.blockScalarHeader;
27576
+ if (!header) {
27577
+ return;
27578
+ }
27579
+ if (header.includes("+") || header.includes("-")) {
27580
+ return;
27581
+ }
27582
+ let shouldWarn = false;
27583
+ const parentDefinitionName = parent?.definition?.key;
27584
+ const tokenDefinitionName = token.definition?.key;
27585
+ const keyName = key && isString(key) ? key.value : void 0;
27586
+ if (parentDefinitionName && [
27587
+ "workflow-env",
27588
+ "job-env",
27589
+ "step-env",
27590
+ "container-env",
27591
+ "step-with",
27592
+ "job-outputs",
27593
+ "workflow-job-with",
27594
+ "workflow-job-secrets"
27595
+ ].includes(parentDefinitionName)) {
27596
+ shouldWarn = true;
27597
+ } else if (ancestors.some((ancestor) => {
27598
+ const ancestorKey = ancestor.definition?.key;
27599
+ return ancestorKey === "matrix" || ancestorKey === "matrix-filter" || ancestorKey === "matrix-filter-item";
27600
+ })) {
27601
+ shouldWarn = true;
27602
+ } else if (tokenDefinitionName && ["workflow-concurrency", "job-concurrency"].includes(tokenDefinitionName)) {
27603
+ shouldWarn = true;
27604
+ } else if (keyName === "group" && parentDefinitionName === "concurrency-mapping") {
27605
+ shouldWarn = true;
27606
+ }
27607
+ if (!shouldWarn) {
27608
+ return;
27609
+ }
27610
+ const blockIndicator = header.startsWith("|") ? "|" : ">";
27611
+ diagnostics.push({
27612
+ message: `Block scalar '${blockIndicator}' implicitly adds a trailing newline that may be unintentional. Use '${blockIndicator}-' to remove it, or '${blockIndicator}+' to explicitly keep it.`,
27613
+ range: mapRange(token.range),
27614
+ severity: import_vscode_languageserver_types6.DiagnosticSeverity.Warning,
27615
+ code: "block-scalar-chomping"
27616
+ });
27617
+ }
26911
27618
 
26912
27619
  // src/connection.ts
26913
27620
  var import_vscode_languageserver = __toESM(require_main7(), 1);
@@ -31255,6 +31962,7 @@ function initConnection(connection) {
31255
31962
  let repos = [];
31256
31963
  const cache = new TTLCache();
31257
31964
  let hasWorkspaceFolderCapability = false;
31965
+ let featureFlags = new FeatureFlags();
31258
31966
  registerLogger(connection.console);
31259
31967
  connection.onInitialize((params) => {
31260
31968
  const capabilities = params.capabilities;
@@ -31269,6 +31977,7 @@ function initConnection(connection) {
31269
31977
  if (options.logLevel !== void 0) {
31270
31978
  setLogLevel(options.logLevel);
31271
31979
  }
31980
+ featureFlags = new FeatureFlags(options.experimentalFeatures);
31272
31981
  const result = {
31273
31982
  capabilities: {
31274
31983
  textDocumentSync: import_vscode_languageserver.TextDocumentSyncKind.Full,
@@ -31293,6 +32002,10 @@ function initConnection(connection) {
31293
32002
  return result;
31294
32003
  });
31295
32004
  connection.onInitialized(() => {
32005
+ const enabledFeatures = featureFlags.getEnabledFeatures();
32006
+ if (enabledFeatures.length > 0) {
32007
+ connection.console.info(`Experimental features enabled: ${enabledFeatures.join(", ")}`);
32008
+ }
31296
32009
  if (hasWorkspaceFolderCapability) {
31297
32010
  connection.workspace.onDidChangeWorkspaceFolders(() => {
31298
32011
  clearCache();
@@ -31311,7 +32024,8 @@ function initConnection(connection) {
31311
32024
  actionsMetadataProvider: getActionsMetadataProvider(client, cache),
31312
32025
  fileProvider: getFileProvider(client, cache, repoContext?.workspaceUri, async (path) => {
31313
32026
  return await connection.sendRequest(Requests.ReadFile, { path });
31314
- })
32027
+ }),
32028
+ featureFlags
31315
32029
  };
31316
32030
  const result = await validate(textDocument, config);
31317
32031
  await connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: result });