Add a type to represent local and remote files

This commit is contained in:
Josh Gross
2023-02-06 15:39:44 -05:00
parent 13aaa381c8
commit f28384e7ea
5 changed files with 104 additions and 4 deletions
+2 -1
View File
@@ -1,6 +1,7 @@
import {TemplateContext} from "../templates/template-context";
import {TemplateToken, TemplateTokenError} from "../templates/tokens/template-token";
import {FileProvider} from "../workflows/file-provider";
import {parseFileReference} from "../workflows/file-reference";
import {parseWorkflow} from "../workflows/workflow-parser";
import {convertConcurrency} from "./converter/concurrency";
import {convertOn} from "./converter/events";
@@ -97,7 +98,7 @@ export async function convertWorkflowTemplate(
}
try {
const file = await fileProvider.getFileContent(job.ref.value);
const file = await fileProvider.getFileContent(parseFileReference(job.ref.value));
const workflow = parseWorkflow(file, context);
if (!workflow.value) {
continue;
@@ -1,5 +1,6 @@
import {File} from "./file";
import {FileReference} from "./file-reference";
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}`;
}
+3 -2
View File
@@ -5,6 +5,7 @@ import {convertWorkflowTemplate} from "./model/convert";
import {TraceWriter} from "./templates/trace-writer";
import {File} from "./workflows/file";
import {FileProvider} from "./workflows/file-provider";
import {fileIdentifier, FileReference} from "./workflows/file-reference";
import {parseWorkflow} from "./workflows/workflow-parser";
interface TestOptions {
@@ -61,8 +62,8 @@ describe("x-lang tests", () => {
}
const testFileProvider: FileProvider = {
getFileContent: async (fileName: string) => {
const file = reusableWorkflows[fileName];
getFileContent: async (ref: FileReference) => {
const file = reusableWorkflows[fileIdentifier(ref)];
if (file) {
return file;
}