History

Make custom tools lint clean

Rhys Sullivan committed 4 months ago

Commit f754da51 parent 2a35fef33 files · +681 −549Browse files

Showing the changes to packages/plugins/apps/src/source/github-source.ts (1 of 33 files). Show all

Unified · Split

packages/plugins/apps/src/source/github-source.ts+81−74
@@ -1,4 +1,4 @@
1import { Data, Effect, Result } from "effect";1import { Data, Effect, Predicate, Result, Schema } from "effect";
2 2
3import { PublishError, type FileDiagnostic } from "../pipeline/discover";3import { PublishError, type FileDiagnostic } from "../pipeline/discover";
4import { PUBLISH_LIMITS, enforcePublishLimits } from "../pipeline/publish";4import { PUBLISH_LIMITS, enforcePublishLimits } from "../pipeline/publish";
@@ -106,37 +106,42 @@ const requestJson = <A>( · 101 unmodified lines
106 input: GitHubSourceInput,106 input: GitHubSourceInput,
107 path: string,107 path: string,
108): Effect.Effect<A, GitHubSourceError> =>108): Effect.Effect<A, GitHubSourceError> =>
109 Effect.tryPromise({109 Effect.gen(function* () {
110 try: async () => {110 const response = yield* Effect.tryPromise({
111 const fetchImpl = input.fetch ?? globalThis.fetch;111 try: async () => {
112 const headers: Record<string, string> = {112 const fetchImpl = input.fetch ?? globalThis.fetch;
113 accept: "application/vnd.github+json",113 const headers: Record<string, string> = {
114 "user-agent": "executor-apps-github-source",114 accept: "application/vnd.github+json",
115 };115 "user-agent": "executor-apps-github-source",
116 if (input.token) headers.authorization = `Bearer ${input.token}`;116 };
117 const response = await fetchImpl(117 if (input.token) headers.authorization = `Bearer ${input.token}`;
118 `${trimBaseUrl(input.baseUrl ?? "https://api.github.com")}${path}`,118 return fetchImpl(`${trimBaseUrl(input.baseUrl ?? "https://api.github.com")}${path}`, {
119 {
120 headers,119 headers,
121 },
122 );
123 if (!response.ok) {
124 throw new GitHubSourceError({
125 message: `GitHub request failed: GET ${path} -> ${response.status}`,
126 status: response.status,
127 path,
128 });120 });
129 }121 },
130 return (await response.json()) as A;122 catch: (cause) =>
131 },123 new GitHubSourceError({
132 catch: (cause) =>124 message: `GitHub request failed: GET ${path}`,
133 cause instanceof GitHubSourceError125 path,
134 ? cause126 cause,
135 : new GitHubSourceError({127 }),
136 message: `GitHub request failed: GET ${path}`,128 });
137 path,129 if (!response.ok) {
138 cause,130 return yield* new GitHubSourceError({
139 }),131 message: `GitHub request failed: GET ${path} -> ${response.status}`,
132 status: response.status,
133 path,
134 });
135 }
136 return yield* Effect.tryPromise({
137 try: () => response.json() as Promise<A>,
138 catch: (cause) =>
139 new GitHubSourceError({
140 message: `GitHub response was not valid JSON: GET ${path}`,
141 path,
142 cause,
143 }),
144 });
140 });145 });
141 146
142interface RepoResponse {147interface RepoResponse {
@@ -254,42 +259,39 @@ const classifyTreeEntry = ( · 111 unmodified lines
254};259};
255 260
256const decodeBlob = (path: string, blob: BlobResponse): Effect.Effect<string, GitHubSourceError> =>261const decodeBlob = (path: string, blob: BlobResponse): Effect.Effect<string, GitHubSourceError> =>
257 Effect.try({262 Effect.gen(function* () {
258 try: () => {263 const encoding = asString(blob.encoding);
259 const encoding = asString(blob.encoding);264 const content = asString(blob.content);
260 const content = asString(blob.content);265 if (!content || encoding !== "base64") {
261 if (!content || encoding !== "base64") {266 return yield* new GitHubSourceError({
262 throw new GitHubSourceError({267 message: `GitHub blob ${path} did not return base64 content`,
263 message: `GitHub blob ${path} did not return base64 content`,268 path,
264 path,269 });
265 });270 }
266 }271 return Buffer.from(content.replace(/\s/g, ""), "base64").toString("utf8");
267 return Buffer.from(content.replace(/\s/g, ""), "base64").toString("utf8");
268 },
269 catch: (cause) =>
270 cause instanceof GitHubSourceError
271 ? cause
272 : new GitHubSourceError({ message: `Failed to decode GitHub blob ${path}`, path, cause }),
273 });272 });
274 273
274const decodeExecutorJson = Schema.decodeUnknownEffect(Schema.UnknownFromJsonString);
275
275const executorDescription = (276const executorDescription = (
276 files: FileSet,277 files: FileSet,
277): Effect.Effect<string | undefined, GitHubSourceError> =>278): Effect.Effect<string | undefined, GitHubSourceError> =>
278 Effect.try({279 Effect.gen(function* () {
279 try: () => {280 const raw = files.get("executor.json");
280 const raw = files.get("executor.json");281 if (!raw) return undefined;
281 if (!raw) return undefined;282 const parsed = yield* decodeExecutorJson(raw).pipe(
282 const parsed = JSON.parse(raw) as unknown;283 Effect.mapError(
283 if (!isRecord(parsed)) return undefined;284 (cause) =>
284 const description = parsed.description;285 new GitHubSourceError({
285 return typeof description === "string" ? description : undefined;286 message: "executor.json is not valid JSON",
286 },287 path: "executor.json",
287 catch: (cause) =>288 cause,
288 new GitHubSourceError({289 }),
289 message: "executor.json is not valid JSON",290 ),
290 path: "executor.json",291 );
291 cause,292 if (!isRecord(parsed)) return undefined;
292 }),293 const description = parsed.description;
294 return typeof description === "string" ? description : undefined;
293 });295 });
294 296
295export const fetchGitHubSource = (297export const fetchGitHubSource = (
@@ -336,7 +338,7 @@ export const fetchGitHubSource = ( · 40 unmodified lines
336 else skipped.push(classified.skipped);338 else skipped.push(classified.skipped);
337 }339 }
338 const treeLimitError = checkTreeLimits(entries);340 const treeLimitError = checkTreeLimits(entries);
339 if (treeLimitError) return yield* Effect.fail(treeLimitError);341 if (treeLimitError) return yield* treeLimitError;
340 342
341 const files = new Map<string, string>();343 const files = new Map<string, string>();
342 for (const entry of entries) {344 for (const entry of entries) {
@@ -348,7 +350,7 @@ export const fetchGitHubSource = ( · 5 unmodified lines
348 files.set(path, yield* decodeBlob(path, blob));350 files.set(path, yield* decodeBlob(path, blob));
349 }351 }
350 const payloadLimitError = enforcePublishLimits(files);352 const payloadLimitError = enforcePublishLimits(files);
351 if (payloadLimitError) return yield* Effect.fail(payloadLimitError);353 if (payloadLimitError) return yield* payloadLimitError;
352 354
353 return {355 return {
354 files,356 files,
@@ -360,17 +362,22 @@ export const fetchGitHubSource = ( · 5 unmodified lines
360 };362 };
361 });363 });
362 364
363const publishErrorToSyncError = (error: PublishError): SyncErrorData => ({365const publishErrorToSyncError = (publishFailure: PublishError): SyncErrorData => {
364 stage: error.stage,366 const stage = publishFailure.stage;
365 message: error.message,367 const message = publishFailure.message;
366 diagnostics: error.diagnostics,368 const diagnostics = publishFailure.diagnostics;
367});369 return { stage, message, diagnostics };
370};
368 371
369const sourceErrorToSyncError = (error: GitHubSourceError): SyncErrorData => ({372const sourceErrorToSyncError = (sourceFailure: GitHubSourceError): SyncErrorData => {
370 stage: "source",373 const message = sourceFailure.message;
371 message: error.message,374 const path = sourceFailure.path;
372 diagnostics: error.path ? [{ path: error.path, message: error.message }] : [],375 return {
373});376 stage: "source",
377 message,
378 diagnostics: path ? [{ path, message }] : [],
379 };
380};
374 381
375const sourceRef = (snapshot: GitHubSourceSnapshot, connection?: string): AppSourceRef => ({382const sourceRef = (snapshot: GitHubSourceSnapshot, connection?: string): AppSourceRef => ({
376 kind: "github",383 kind: "github",
@@ -391,7 +398,7 @@ export const syncGitHubSource = (input: SyncGitHubSourceInput): Effect.Effect<Gi · 14 unmodified lines
391 tools: [],398 tools: [],
392 skipped: [],399 skipped: [],
393 errors: [400 errors: [
394 error instanceof PublishError401 Predicate.isTagged("PublishError")(error)
395 ? publishErrorToSyncError(error)402 ? publishErrorToSyncError(error)
396 : sourceErrorToSyncError(error),403 : sourceErrorToSyncError(error),
397 ],404 ],