Add a type to represent local and remote files
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import {TemplateContext} from "../templates/template-context";
|
import {TemplateContext} from "../templates/template-context";
|
||||||
import {TemplateToken, TemplateTokenError} from "../templates/tokens/template-token";
|
import {TemplateToken, TemplateTokenError} from "../templates/tokens/template-token";
|
||||||
import {FileProvider} from "../workflows/file-provider";
|
import {FileProvider} from "../workflows/file-provider";
|
||||||
|
import {parseFileReference} from "../workflows/file-reference";
|
||||||
import {parseWorkflow} from "../workflows/workflow-parser";
|
import {parseWorkflow} from "../workflows/workflow-parser";
|
||||||
import {convertConcurrency} from "./converter/concurrency";
|
import {convertConcurrency} from "./converter/concurrency";
|
||||||
import {convertOn} from "./converter/events";
|
import {convertOn} from "./converter/events";
|
||||||
@@ -97,7 +98,7 @@ export async function convertWorkflowTemplate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const file = await fileProvider.getFileContent(job.ref.value);
|
const file = await fileProvider.getFileContent(parseFileReference(job.ref.value));
|
||||||
const workflow = parseWorkflow(file, context);
|
const workflow = parseWorkflow(file, context);
|
||||||
if (!workflow.value) {
|
if (!workflow.value) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {File} from "./file";
|
import {File} from "./file";
|
||||||
|
import {FileReference} from "./file-reference";
|
||||||
|
|
||||||
export interface FileProvider {
|
export interface FileProvider {
|
||||||
getFileContent(path: string): Promise<File>;
|
getFileContent(ref: FileReference): Promise<File>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import {parseFileReference} from "./file-reference";
|
||||||
|
|
||||||
|
describe("parseFileReference", () => {
|
||||||
|
it("parses local file reference", () => {
|
||||||
|
const ref = parseFileReference("./workflow/path");
|
||||||
|
expect(ref).toEqual({
|
||||||
|
path: "workflow/path"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("parses local file references with an empty path", () => {
|
||||||
|
const ref = parseFileReference("./");
|
||||||
|
expect(ref).toEqual({
|
||||||
|
path: ""
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("parses remote file reference", () => {
|
||||||
|
const ref = parseFileReference("owner/repo/path@version");
|
||||||
|
expect(ref).toEqual({
|
||||||
|
owner: "owner",
|
||||||
|
repository: "repo",
|
||||||
|
path: "path",
|
||||||
|
version: "version"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("parses remote file reference with an empty path", () => {
|
||||||
|
const ref = parseFileReference("owner/repo@version");
|
||||||
|
expect(ref).toEqual({
|
||||||
|
owner: "owner",
|
||||||
|
repository: "repo",
|
||||||
|
path: "",
|
||||||
|
version: "version"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("parses remote file reference with slashes in the version", () => {
|
||||||
|
const ref = parseFileReference("owner/repo@feature-branch/dev");
|
||||||
|
expect(ref).toEqual({
|
||||||
|
owner: "owner",
|
||||||
|
repository: "repo",
|
||||||
|
path: "",
|
||||||
|
version: "feature-branch/dev"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws for malformed remote file references", () => {
|
||||||
|
expect(() => parseFileReference("owner/repo/path")).toThrowError("Invalid file reference: owner/repo/path");
|
||||||
|
|
||||||
|
expect(() => parseFileReference("owner/repo/path@")).toThrowError("Invalid file reference: owner/repo/path@");
|
||||||
|
|
||||||
|
expect(() => parseFileReference("owner@")).toThrowError("Invalid file reference: owner@");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
export type FileReference = LocalFileReference | RemoteFileReference;
|
||||||
|
|
||||||
|
export type LocalFileReference = {
|
||||||
|
path: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RemoteFileReference = {
|
||||||
|
repository: string;
|
||||||
|
owner: string;
|
||||||
|
path: string;
|
||||||
|
version: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parseFileReference(ref: string): FileReference {
|
||||||
|
if (ref.startsWith("./")) {
|
||||||
|
return {
|
||||||
|
path: ref.substring(2)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const [remotePath, version] = ref.split("@");
|
||||||
|
const [owner, repository, ...pathSegments] = remotePath.split("/").filter(s => s.length > 0);
|
||||||
|
|
||||||
|
if (!owner || !repository || !version) {
|
||||||
|
throw new Error(`Invalid file reference: ${ref}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
repository,
|
||||||
|
owner,
|
||||||
|
path: pathSegments.join("/"),
|
||||||
|
version
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fileIdentifier(ref: FileReference): string {
|
||||||
|
if (!("repository" in ref)) {
|
||||||
|
return "./" + ref.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${ref.owner}/${ref.repository}/${ref.path}@${ref.version}`;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import {convertWorkflowTemplate} from "./model/convert";
|
|||||||
import {TraceWriter} from "./templates/trace-writer";
|
import {TraceWriter} from "./templates/trace-writer";
|
||||||
import {File} from "./workflows/file";
|
import {File} from "./workflows/file";
|
||||||
import {FileProvider} from "./workflows/file-provider";
|
import {FileProvider} from "./workflows/file-provider";
|
||||||
|
import {fileIdentifier, FileReference} from "./workflows/file-reference";
|
||||||
import {parseWorkflow} from "./workflows/workflow-parser";
|
import {parseWorkflow} from "./workflows/workflow-parser";
|
||||||
|
|
||||||
interface TestOptions {
|
interface TestOptions {
|
||||||
@@ -61,8 +62,8 @@ describe("x-lang tests", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const testFileProvider: FileProvider = {
|
const testFileProvider: FileProvider = {
|
||||||
getFileContent: async (fileName: string) => {
|
getFileContent: async (ref: FileReference) => {
|
||||||
const file = reusableWorkflows[fileName];
|
const file = reusableWorkflows[fileIdentifier(ref)];
|
||||||
if (file) {
|
if (file) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user