@ethicdevs/gitfoss | Show object: 7ecdd3bc3dd84124ff0809fd590e00f633528b6f ∙ GitFOSS
feat(pipelines): make it work
+ 120
- 29
@@ -1,5 +1,5 @@
 {
-  "_generatedAtUnix": 1778680701304,
+  "_generatedAtUnix": 1778731850286,
   "_hashAlgorithm": "sha1",
   "_version": 2,
   "assets": {

...
@@ -138,7 +138,7 @@
       "pathSource": "./app/views/pipelines/PipelineStagesView.tsx"
     },
     "PipelinesView": {
-      "hash": "a194e274b2b11c5e9facd86ba669719874399f99",
+      "hash": "8d672f194ee7d56ba6cae6b0cc7f5d96f6514ab7",
       "pathSource": "./app/views/pipelines/PipelinesView.tsx"
     },
     "RepositoryBrowserView": {

...
@@ -182,7 +182,7 @@
       "pathSource": "./app/views/repositoryPullRequests/RepositoryPullRequestDetailsView.tsx"
     },
     "RepositoryPullRequestsView": {
-      "hash": "c5d1055d3691fcdb65c23d03f5a712abcadff82a",
+      "hash": "48e8ba878f5afa28544a6722e5ce675eef5000b5",
       "pathSource": "./app/views/repositoryPullRequests/RepositoryPullRequestsView.tsx"
     },
     "SettingsKeyAddView": {

app/components/DrawerPrimary.tsx
@@ -178,12 +178,14 @@ export const DrawerPrimary = ({
             themeScheme={themeScheme}
             href={pathFiles}
             className={
-              (commonProps.path!.startsWith(pathFiles) ||
+              ((!commonProps.path!.startsWith(pathPipelines) === false &&
+                commonProps.path!.startsWith(pathFiles)) ||
                 [pathFiles, pathRepo, pathRepoTrailing].some(
                   (p) =>
                     commonProps.path === p || commonProps.path!.startsWith(p),
                 )) &&
-              commonProps.path!.startsWith(pathPulls) === false
+              commonProps.path!.startsWith(pathPulls) === false &&
+              commonProps.path!.startsWith(pathPipelines) === false
                 ? "active"
                 : undefined
             }

...
@@ -192,12 +194,14 @@ export const DrawerPrimary = ({
             <span>Files</span>
             <FolderIcon
               color={
-                (commonProps.path!.startsWith(pathFiles) ||
+                ((!commonProps.path!.startsWith(pathPipelines) === false &&
+                  commonProps.path!.startsWith(pathFiles)) ||
                   [pathFiles, pathRepo, pathRepoTrailing].some(
                     (p) =>
                       commonProps.path === p || commonProps.path!.startsWith(p),
                   )) &&
-                commonProps.path!.startsWith(pathPulls) === false
+                commonProps.path!.startsWith(pathPulls) === false &&
+                commonProps.path!.startsWith(pathPipelines) === false
                   ? NamedColors.TEXT_DEFAULT[themeScheme]
                   : NamedColors.TEXT_MUTED[themeScheme]
               }

app/controllers/pipelines/getPipelinesView.ts
@@ -1,27 +1,70 @@
 // 1st-party
 import type { ReqHandler } from "@ethicdevs/react-monolith";
+import { ResourceVisibility } from "@prisma/client";
 // app
 import { AppRoute, AppRouteParams } from "../../routes.defs";
+// app services
+import { makeOrganizationService } from "../../services/organization";
 import { makePipelineService } from "../../services/pipelines";
+import { makeRepositoryService } from "../../services/repository";
+import { makeUsersService } from "../../services/user";
+// app views
 import PipelinesView, {
   PipelinesViewProps,
 } from "../../views/pipelines/PipelinesView";
 
-const getPipelinesView: ReqHandler<
+const getRepositoryPipelinesView: ReqHandler<
   AppRouteParams,
-  AppRoute.REPOSITORY_PIPELINES
+  AppRoute.REPOSITORY_PULL_REQUESTS
 > = async (request, reply) => {
   const { orgSlug, repoSlug } = request.params;
 
+  const orgService = makeOrganizationService({ request });
   const pipelineService = makePipelineService({ request, runner: {} });
-  const pipelines = await pipelineService.listByRepo(orgSlug, repoSlug);
+  const repoService = makeRepositoryService({ request });
+  const usersService = makeUsersService({ request });
+
+  const currentUser =
+    request.session.data.authenticated &&
+    request.session.data.curr_user_uid != null
+      ? await usersService.getUserById(request.session.data.curr_user_uid)
+      : null;
+
+  const parentOrg = await orgService.getOrganizationBySlug(orgSlug);
+
+  if (parentOrg == null) {
+    return reply.status(404).callNotFound();
+  }
+
+  const repo = await repoService.getRepository(orgSlug, repoSlug);
+
+  if (repo == null) {
+    return reply.status(404).callNotFound();
+  }
+
+  if (repo.visibility === ResourceVisibility.PRIVATE) {
+    if (currentUser == null) {
+      return reply.status(404).callNotFound();
+    } else if (
+      (await repoService.canUserAccessRepository(currentUser, repo)) === false
+    ) {
+      return reply.status(404).callNotFound();
+    }
+  }
+
+  const pipelines = await pipelineService.listByRepo(
+    parentOrg.slug,
+    repo.slug,
+    (request.query as any)?.filter ?? "passed",
+  );
 
   const reqHandler = reply.makeRequestHandler(request, reply);
   return reqHandler<PipelinesViewProps>(PipelinesView.name, {
+    parentOrg,
     pipelines,
-    orgSlug,
-    repoSlug,
+    repo,
+    pipelinesFilter: (request.query as any)?.filter ?? "passed",
   });
 };
 
-export default getPipelinesView;
+export default getRepositoryPipelinesView;

app/services/pipelines/listByRepo.ts
@@ -1,14 +1,18 @@
 // 1st-party
 import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
-import type { Pipeline } from "@prisma/client";
-import type { PipelineServiceDeps } from "./types";
+import { Pipeline, PipelineStatus } from "@prisma/client";
+import type { PipelineServiceDeps, PipelinesFilter } from "./types";
 
 const makeListByRepo: ServiceMethodFactory<
   PipelineServiceDeps,
   [string, string],
   Promise<Pipeline[]>
 > = ({ request }) => {
-  return async (orgSlug: string, repoSlug: string) => {
+  return async (
+    orgSlug: string,
+    repoSlug: string,
+    filter?: PipelinesFilter,
+  ) => {
     return request.prisma.pipeline.findMany({
       where: {
         repo: {

...
@@ -17,6 +21,16 @@ const makeListByRepo: ServiceMethodFactory<
           },
           slug: repoSlug,
         },
+        status:
+          filter != null && filter !== "all"
+            ? {
+                passed: PipelineStatus.PASSED,
+                pending: PipelineStatus.PENDING,
+                running: PipelineStatus.RUNNING,
+                failed: PipelineStatus.FAILED,
+                canceled: PipelineStatus.CANCELED,
+              }[filter || "passed"]
+            : undefined,
       },
       orderBy: { createdAt: "desc" },
     });

app/services/pipelines/types.ts
@@ -15,8 +15,20 @@ export interface PipelineServiceDeps {
   runner: any; // GitfossCIRunnerClient
 }
 
+export type PipelinesFilter =
+  | "all"
+  | "passed"
+  | "pending"
+  | "running"
+  | "failed"
+  | "canceled";
+
 export type PipelineServiceAPI = {
-  listByRepo(orgSlug: string, repoSlug: string): Promise<Pipeline[]>;
+  listByRepo(
+    orgSlug: string,
+    repoSlug: string,
+    filter?: PipelinesFilter,
+  ): Promise<Pipeline[]>;
   listByRepoId(repoId: string): Promise<Pipeline[]>;
   getRepoPipelineManifest(orgSlug: string, repoSlug: string): Promise<Manifest>;
   parsePipelineManifest(manifestJsonOrYml: string): Manifest;

app/views/pipelines/PipelinesView.tsx
@@ -18,21 +18,27 @@ import { Colors, NamedColors } from "../../utils/style";
 import { IslandWrapper } from "../../components/IslandWrapper.styled";
 import RepositoryHero from "../../islands/RepositoryHero";
 
-type PipelinesFilter = "all" | "pending" | "running" | "failed" | "canceled";
+type PipelinesFilter =
+  | "all"
+  | "passed"
+  | "pending"
+  | "running"
+  | "failed"
+  | "canceled";
 
-export interface RepositoryPipelinesViewProps extends CommonProps {
+export interface PipelinesViewProps extends CommonProps {
   parentOrg: Organization;
   pipelines: Pipeline[];
   repo: RepositoryWithForkedFromRepo;
   pipelinesFilter?: PipelinesFilter;
 }
 
-const RepositoryPipelinesView: ReactView<RepositoryPipelinesViewProps> = ({
+const PipelinesView: ReactView<PipelinesViewProps> = ({
   commonProps,
   parentOrg,
-  pipelines,
   repo,
-  pipelinesFilter = "success",
+  pipelines,
+  pipelinesFilter = "passed",
 }) => {
   return (
     <Layout

...
@@ -48,8 +54,8 @@ const RepositoryPipelinesView: ReactView<RepositoryPipelinesViewProps> = ({
             forkedFromRepo={repo.forkedFromRepo}
             forksCount={repo.forks.length}
             parentOrg={parentOrg}
-            path={`Pipelines`}
             repo={repo}
+            path={`Pipelines`}
             showForkButton={false}
             showNewButton
             newButtonText={"Trigger Pipeline"}

...
@@ -113,7 +119,7 @@ const RepositoryPipelinesView: ReactView<RepositoryPipelinesViewProps> = ({
               }`}
             >
               <Grid.Row nowrap gap={8} alignItems={"center"}>
-                <span>Passed!</span>
+                <span>Passed</span>
                 <Chip themeScheme={commonProps.themeScheme}>
                   {commonProps.layoutCounters!.pullsOpen}
                 </Chip>

...
@@ -260,8 +266,14 @@ const RepositoryPipelinesView: ReactView<RepositoryPipelinesViewProps> = ({
               alignItems={"center"}
               style={{ minHeight: "70vh" }}
             >
-              <h1 style={{ margin: 0 }}>No Pull Request Yet</h1>
-              <p style={{ maxWidth: "62%", textAlign: "center" }}>
+              <h1 style={{ margin: 0 }}>No Pipeline Yet</h1>
+              <p
+                style={{
+                  maxWidth: "62%",
+                  textAlign: "center",
+                  lineHeight: 1.8,
+                }}
+              >
                 <span>Be the change you want to see, </span>
                 <a
                   href={buildRouteLink(

...
@@ -285,5 +297,5 @@ const RepositoryPipelinesView: ReactView<RepositoryPipelinesViewProps> = ({
   );
 };
 
-RepositoryPipelinesView.displayName = "RepositoryPipelinesView";
-export default RepositoryPipelinesView;
+PipelinesView.displayName = "PipelinesView";
+export default PipelinesView;

app/views/repositoryPullRequests/RepositoryPullRequestsView.tsx
@@ -261,7 +261,13 @@ const RepositoryPullRequestsView: ReactView<
               style={{ minHeight: "70vh" }}
             >
               <h1 style={{ margin: 0 }}>No Pull Request Yet</h1>
-              <p style={{ maxWidth: "62%", textAlign: "center" }}>
+              <p
+                style={{
+                  maxWidth: "62%",
+                  textAlign: "center",
+                  lineHeight: 1.8,
+                }}
+              >
                 <span>Be the change you want to see, </span>
                 <a
                   href={buildRouteLink(