Skip to content

Commit

Permalink
Merge pull request #2 from Design-System-Project/feature/tfr2-97-repo…
Browse files Browse the repository at this point in the history
…sitory-get-deployment-status-and-display-versions

add release selection and tokens display per release
  • Loading branch information
tomasfrancisco authored Aug 15, 2024
2 parents 5af17e0 + f8876dc commit bc266d5
Show file tree
Hide file tree
Showing 24 changed files with 408 additions and 173 deletions.
27 changes: 8 additions & 19 deletions apps/dashboard/src/app/(dashboard)/integrations/page.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,17 @@
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@ds-project/components';
import { MainContent } from '@/components';
import { GithubProvider } from './providers/github/_components';
import { FigmaProvider } from './providers/figma/_components';

export default function Page() {
return (
<Card className="w-full">
<CardHeader>
<CardTitle size="2xl" weight="medium">
<h1>Integrations</h1>
</CardTitle>
<CardDescription>
<p>Authorize and manage integrations</p>
</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-4">
<MainContent
description="Authorize and manage integrations"
title="Integrations"
>
<div className="flex flex-col gap-2">
<GithubProvider />
<FigmaProvider />
</CardContent>
</Card>
</div>
</MainContent>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,40 +56,42 @@ export async function GithubProvider() {
</Text>
</div>

<form action={selectRepository} className="flex gap-2">
<Select
defaultValue={installation?.data.repositoryId?.toString()}
name="repositoryId"
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Repositories" />
</SelectTrigger>
<SelectContent>
{repositories?.map((repository) => (
<SelectItem key={repository.id} value={String(repository.id)}>
{repository.name}
</SelectItem>
))}
</SelectContent>
</Select>
<Input
name="installationId"
type="hidden"
value={installation?.data.installationId}
/>
{installation ? (
<form action={selectRepository} className="flex gap-2">
<Select
defaultValue={installation.data.repositoryId?.toString()}
name="repositoryId"
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Repositories" />
</SelectTrigger>
<SelectContent>
{repositories?.map((repository) => (
<SelectItem key={repository.id} value={String(repository.id)}>
{repository.name}
</SelectItem>
))}
</SelectContent>
</Select>
<Input
name="installationId"
type="hidden"
value={installation.data.installationId}
/>

<Button type="submit">Update</Button>
</form>
<Button type="submit">Update</Button>
</form>
) : null}

<Button asChild variant={isInstallationActive ? 'outline' : 'default'}>
<Link href={installationUrl}>
{isInstallationActive ? 'Configure' : 'Authorize'}
</Link>
</Button>

<Button>
{/* <Button>
<Link href="/integrations/providers/github">Tokens</Link>
</Button>
</Button> */}
</div>
);
}
6 changes: 4 additions & 2 deletions apps/dashboard/src/app/(dashboard)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ export default async function RootLayout({
return (
<html lang="en">
<body className={cn('flex flex-col items-center', inter.className)}>
<Navigation className="mt-6 px-2" projects={projects} />
<main className="flex min-h-screen w-full flex-col items-center p-24">
<header className="sticky top-0 w-full">
<Navigation className="px-2 pt-2" projects={projects} />
</header>
<main className="flex min-h-screen w-full flex-col items-center py-2">
{children}
</main>
</body>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
'use server';
import type { DesignTokens } from 'style-dictionary/types';
import type { Octokit } from '@octokit/core';
import {
getGithubInstallation,
getGithubIntegration,
getGithubRepository,
} from '@/lib/github';
import { isAuthenticated } from '@/lib/supabase/server/utils/is-authenticated';
import { config } from '@/config';

async function searchFileSha({
installation,
owner,
path,
repo,
treeSha,
index = 0,
}: {
installation: Octokit;
owner: string;
repo: string;
treeSha: string;
path: string[];
index?: number;
}) {
const { data: treeData } = await installation.request(
'GET /repos/{owner}/{repo}/git/trees/{tree_sha}',
{
owner,
repo,
tree_sha: treeSha,
}
);

const treeOrFile = treeData.tree.find(
(treeItem) => treeItem.path === path[index]
);
if (!treeOrFile?.sha) {
return null;
}
if (index === path.length - 1) {
return treeOrFile.sha;
}

return searchFileSha({
installation,
owner,
repo,
treeSha: treeOrFile.sha,
path,
index: index + 1,
});
}

export async function fetchReleaseTokens(releaseId: number) {
if (!(await isAuthenticated())) {
throw new Error('Not authenticated');
}

const repository = await getGithubRepository();
const integration = await getGithubIntegration();
const installation = await getGithubInstallation(integration);

const { data: release } = await installation.request(
'GET /repos/{owner}/{repo}/releases/{release_id}',
{
owner: repository.owner.login,
repo: repository.name,
release_id: releaseId,
}
);

const { data: tagName } = await installation.request(
'GET /repos/{owner}/{repo}/git/ref/{ref}',
{
owner: repository.owner.login,
repo: repository.name,
ref: `tags/${release.tag_name}`,
}
);

// First, get the file sha from the commit
const { data: tagSha } = await installation.request(
'GET /repos/{owner}/{repo}/git/tags/{tag_sha}',
{
owner: repository.owner.login,
repo: repository.name,
tag_sha: tagName.object.sha,
}
);

const { data: commitSha } = await installation.request(
'GET /repos/{owner}/{repo}/git/commits/{commit_sha}',
{
owner: repository.owner.login,
repo: repository.name,
commit_sha: tagSha.object.sha,
}
);

const tokensPath = [...config.gitTokensPath.split('/'), 'tokens.json'];
const fileSha = await searchFileSha({
installation,
owner: repository.owner.login,
treeSha: commitSha.tree.sha,
repo: repository.name,
path: tokensPath,
});

if (!fileSha) {
throw new Error('File not found');
}

const { data: file } = await installation.request(
'GET /repos/{owner}/{repo}/git/blobs/{file_sha}',
{
owner: repository.owner.login,
repo: repository.name,
file_sha: fileSha,
}
);

const tokens = Buffer.from(
file.content,
file.encoding as BufferEncoding
).toString();

return JSON.parse(tokens) as DesignTokens;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use server';
import {
getGithubInstallation,
getGithubIntegration,
getGithubRepository,
} from '@/lib/github';
import { isAuthenticated } from '@/lib/supabase/server/utils/is-authenticated';

export async function fetchReleases() {
if (!(await isAuthenticated())) {
throw new Error('Not authenticated');
}

const repository = await getGithubRepository();
const integration = await getGithubIntegration();
const installation = await getGithubInstallation(integration);

const { data } = await installation.request(
'GET /repos/{owner}/{repo}/releases',
{
owner: repository.owner.login,
repo: repository.name,
}
);

return data;
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './update-tokens.action';
export * from './fetch-releases.action';
export * from './tokens.action';

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './push-button';
export * from './select-releases';

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use client';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@ds-project/components';
import { useCallback, useEffect, useState } from 'react';
import type { DesignTokens } from 'style-dictionary/types';
import { InstallRelease, JsonBlock } from '@/components';
import type { fetchReleases } from '../_actions';
import { fetchReleaseTokens } from '../_actions/fetch-release-tokens.action';

interface SelectReleasesProps {
releases: Awaited<ReturnType<typeof fetchReleases>>;
}

export function SelectReleases({ releases }: SelectReleasesProps) {
const [selectedRelease, setSelectedRelease] =
useState<SelectReleasesProps['releases'][number]>();
const [tokens, setTokens] = useState<DesignTokens>();

const onReleaseChange = useCallback(
(selectedReleaseId: string) => {
const newSelectedRelease = releases.find(
(release) => String(release.id) === selectedReleaseId
);
setSelectedRelease(newSelectedRelease);
},
[releases]
);

useEffect(() => {
if (!selectedRelease?.id) return;

fetchReleaseTokens(selectedRelease.id)
.then((_tokens) => {
setTokens(_tokens);
})
.catch((error) => {
// eslint-disable-next-line no-console -- TODO: replace with monitoring
console.error('Error fetching release tokens', error);
});
}, [selectedRelease?.id]);

return (
<>
<div className="flex justify-between">
<Select
onValueChange={onReleaseChange}
value={selectedRelease?.id.toString()}
>
<SelectTrigger className="max-w-sm">
<SelectValue placeholder="Release" />
</SelectTrigger>
<SelectContent>
{releases.map((release) => (
<SelectItem key={release.id} value={String(release.id)}>
{release.name}
</SelectItem>
))}
</SelectContent>
</Select>
{selectedRelease?.name ? (
<InstallRelease packageName={selectedRelease.name} />
) : null}
</div>
{tokens ? <JsonBlock src={tokens} /> : null}
</>
);
}
Loading

0 comments on commit bc266d5

Please sign in to comment.