Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion languageservice/src/complete.expressions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1164,7 +1164,16 @@ jobs:
`;

const result = await complete(...getPositionFromCursor(input), {contextProviderConfig});
expect(result.map(x => x.label)).toEqual(["check_run_id", "container", "services", "status"]);
expect(result.map(x => x.label)).toEqual([
"check_run_id",
"container",
"services",
"status",
"workflow_file_path",
"workflow_ref",
"workflow_repository",
"workflow_sha"
]);
});

it("job context is suggested within a job output", async () => {
Expand Down
12 changes: 12 additions & 0 deletions languageservice/src/context-providers/descriptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,18 @@
},
"check_run_id": {
"description": "The unique identifier of the check run for this job."
},
"workflow_file_path": {
"description": "The path of the workflow file that contains the job. For example, `.github/workflows/my-workflow.yml`."
},
"workflow_ref": {
"description": "The ref of the workflow file that contains the job. For example, `octocat/hello-world/.github/workflows/my-workflow.yml@refs/heads/my_branch`."
},
"workflow_repository": {
"description": "The owner and repository name of the workflow file that contains the job. For example, `octocat/Hello-World`."
},
"workflow_sha": {
"description": "The commit SHA of the workflow file that contains the job."
}
},
"secrets": {
Expand Down
21 changes: 21 additions & 0 deletions languageservice/src/context-providers/job.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ describe("job context", () => {

expect(context.get("status")).toBeDefined();
expect(context.get("check_run_id")).toBeDefined();
expect(context.get("workflow_ref")).toBeDefined();
expect(context.get("workflow_sha")).toBeDefined();
expect(context.get("workflow_repository")).toBeDefined();
expect(context.get("workflow_file_path")).toBeDefined();
expect(context.get("container")).toBeUndefined();
expect(context.get("services")).toBeUndefined();
});
Expand Down Expand Up @@ -173,4 +177,21 @@ describe("job context", () => {
expect(redis.getDescription("ports")).toBeDefined();
});
});

describe("workflow context fields", () => {
it("includes workflow context fields with descriptions", () => {
const workflowContext = {job: {}} as WorkflowContext;
const context = getJobContext(workflowContext);

expect(context.get("workflow_ref")).toBeDefined();
expect(context.get("workflow_sha")).toBeDefined();
expect(context.get("workflow_repository")).toBeDefined();
expect(context.get("workflow_file_path")).toBeDefined();

expect(context.getDescription("workflow_ref")).toBeDefined();
expect(context.getDescription("workflow_sha")).toBeDefined();
expect(context.getDescription("workflow_repository")).toBeDefined();
expect(context.getDescription("workflow_file_path")).toBeDefined();
});
});
});
6 changes: 6 additions & 0 deletions languageservice/src/context-providers/job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ export function getJobContext(workflowContext: WorkflowContext): DescriptionDict
// Check run ID
jobContext.add("check_run_id", new data.StringData(""), getDescription("job", "check_run_id"));

// Workflow context fields (populated at runtime for reusable workflow jobs)
jobContext.add("workflow_file_path", new data.StringData(""), getDescription("job", "workflow_file_path"));
jobContext.add("workflow_ref", new data.StringData(""), getDescription("job", "workflow_ref"));
jobContext.add("workflow_repository", new data.StringData(""), getDescription("job", "workflow_repository"));
jobContext.add("workflow_sha", new data.StringData(""), getDescription("job", "workflow_sha"));
Comment on lines +45 to +49
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

The function-level doc comment above getJobContext says it returns only container/services/status/check_run_id, but this change adds workflow_* fields too. Please update the doc comment so it accurately reflects the returned context keys.

Copilot uses AI. Check for mistakes.

return jobContext;
}

Expand Down
18 changes: 18 additions & 0 deletions languageservice/src/validate.expressions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,24 @@ jobs:
expect(result).toEqual([]);
});

it("job.workflow_ref", async () => {
const input = `
on: push

jobs:
test:
runs-on: ubuntu-latest
steps:
- run: echo \${{ job.workflow_ref }}
- run: echo \${{ job.workflow_sha }}
- run: echo \${{ job.workflow_repository }}
- run: echo \${{ job.workflow_file_path }}
Comment on lines +435 to +446
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

This test title mentions only job.workflow_ref, but the body validates four fields (workflow_ref, workflow_sha, workflow_repository, workflow_file_path). Consider renaming the test to cover all four (e.g., job.workflow_*) to keep test output clear when failures occur.

Copilot uses AI. Check for mistakes.
`;
const result = await validate(createDocument("wf.yaml", input));

expect(result).toEqual([]);
});

it("job.services.<service_id>", async () => {
const input = `
on: push
Expand Down
Loading