Skip to content

Commit b4c7cdf

Browse files
Streamline build and commit metadata acquisition
Build info now properly uses commit info and unused types functions are removed.
1 parent 8533fb7 commit b4c7cdf

14 files changed

Lines changed: 193 additions & 126 deletions

File tree

components/Blog/layout.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { blogInitialsFont } from "@/lib/fonts";
22
import Link from "next/link";
33
import { ThemeSwitch } from "@/components/ui/ThemeSwitch";
4-
import { BuildInfo } from "@/lib/buildInfo";
4+
import { BuildInfo, SerializedBuildInfo } from "@/lib/buildInfo";
55
import BuildStamp from "@/components/BuildStamp";
66
type Props = {
77
children: React.ReactNode;
8-
websiteWideBuildInfo?: BuildInfo;
8+
websiteWideBuildInfo?: SerializedBuildInfo;
99
};
1010

1111
function Header() {
@@ -14,9 +14,9 @@ function Header() {
1414
<div className="flex justify-center">
1515
<Link
1616
href="/blog"
17-
className={`bold ${blogInitialsFont.className} text-4xl`}
17+
className={`bold ${blogInitialsFont.className} text-4xl relative inline-block after:content-['.'] after:absolute after:left-full`}
1818
>
19-
mnf.
19+
mnf
2020
</Link>
2121
</div>
2222
<div className="hidden md:flex md:gap-4">
@@ -38,7 +38,7 @@ const Layout = (props: Props) => {
3838
{props.websiteWideBuildInfo ? (
3939
<div className="flex-grow flex flex-col justify-end">
4040
<footer className="w-full text-muted-foreground mt-auto">
41-
<BuildStamp buildInfo={props.websiteWideBuildInfo} />
41+
<BuildStamp serializedBuildInfo={props.websiteWideBuildInfo} />
4242
</footer>
4343
</div>
4444
) : null}

components/BuildStamp.tsx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
11
import React, { useMemo, useState } from "react";
2-
import { type BuildInfo, type BuildCommitInfo } from "@/lib/buildInfo";
2+
import {
3+
type BuildInfo,
4+
CommitEntry,
5+
SerializedBuildInfo,
6+
} from "@/lib/buildInfo";
37

48
import { CodeXml, DatabaseIcon } from "lucide-react";
59
import { Button } from "@/components/ui/button";
610
import Link from "next/link";
711
import { ClockIcon, CommitIcon } from "@radix-ui/react-icons";
812
import { blogInitialsFont } from "@/lib/fonts";
913

10-
export function computeGithubURLs(commit: BuildCommitInfo) {
14+
export function computeGithubURLs(buildInfo: SerializedBuildInfo) {
1115
return {
12-
repoURL: `https://github.com/michaelfortunato/${commit.repo}`,
13-
commitURL: `https://github.com/michaelfortunato/${commit.repo}/commit/${commit.hash}`,
14-
branchURL: `https://github.com/michaelfortunato/${commit.repo}/tree/${commit.branch}`,
16+
repoURL: `https://github.com/michaelfortunato/personal-website`,
17+
commitURL: `https://github.com/michaelfortunato/personal-website/commit/${buildInfo.buildCommitEntry.commitHash}`,
18+
branchURL: `https://github.com/michaelfortunato/personal-website/tree/${buildInfo.branch}`,
1519
};
1620
}
1721

1822
const BuildStamp: React.FC<{
19-
buildInfo: BuildInfo;
23+
serializedBuildInfo: SerializedBuildInfo;
2024
triggerFadeIn?: boolean;
21-
}> = ({
22-
buildInfo: {
23-
commitInfo: { repo, hash, branch },
24-
buildTimestamp,
25-
},
26-
}) => {
25+
}> = ({ serializedBuildInfo }) => {
2726
const { commitURL, branchURL } = useMemo(
28-
() => computeGithubURLs({ repo, hash, branch }),
29-
[repo, hash, branch],
27+
() => computeGithubURLs(serializedBuildInfo),
28+
[serializedBuildInfo.buildCommitEntry.commitHash],
3029
);
30+
3131
return (
3232
<div className="flex justify-center p-2 pb-4">
3333
<div className="flex flex-col">
@@ -45,21 +45,23 @@ const BuildStamp: React.FC<{
4545
<div>
4646
<ClockIcon />
4747
</div>
48-
<Link href={commitURL}>{buildTimestamp}</Link>
48+
<Link href={commitURL}>{serializedBuildInfo.buildTimestamp}</Link>
4949
</div>
5050
<div className="flex items-center gap-1">
5151
<div>
5252
<DatabaseIcon width="15px" />
5353
</div>
5454
<div>
5555
<Link href={branchURL}>
56-
{repo}/{branch}
56+
{"personal-website/" + serializedBuildInfo.branch}
5757
</Link>
5858
</div>
5959
</div>
6060
<div className="inline-flex items-center">
6161
<CommitIcon className="translate-y-[1px]" />
62-
<Link href={commitURL}>{hash}</Link>
62+
<Link href={commitURL}>
63+
{serializedBuildInfo.buildCommitEntry.shortCommitHash}
64+
</Link>
6365
</div>
6466
</div>
6567
</div>

components/Name.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ export default function Name(props: NameProps) {
5050
<>
5151
{isClient && (
5252
<div className="relative flex justify-center overflow-visible pt-[2%] text-center text-[56px] text-[#264653]">
53-
<div className="flex gap-6">
54-
<div className="inline-block">
53+
<div className="md:flex gap-6">
54+
<div>
5555
<LayoutGroup>
5656
{props.firstName.split("").map((_, index) => (
5757
<Letter
@@ -62,7 +62,7 @@ export default function Name(props: NameProps) {
6262
))}
6363
</LayoutGroup>
6464
</div>
65-
<div className="inline-block">
65+
<div>
6666
<LayoutGroup>
6767
{props.lastName.split("").map((_, index) => (
6868
<Letter

components/RootPageLayout.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { PropsWithChildren } from "react";
22
import Navbar from "./Nav/Navbar";
33
import { Toaster } from "./ui/toaster";
4-
import { BuildInfo } from "@/lib/buildInfo";
4+
import { BuildInfo, SerializedBuildInfo } from "@/lib/buildInfo";
55
import BuildStamp from "@/components/BuildStamp";
66

77
export type RootPageStyle = {
@@ -41,15 +41,15 @@ const pageConfigs: Record<string, RootPageStyle> = {
4141

4242
export default function RootPageLayout({
4343
children,
44-
buildInfo,
45-
}: PropsWithChildren<{ buildInfo: BuildInfo }>) {
44+
serializedBuildInfo,
45+
}: PropsWithChildren<{ serializedBuildInfo: SerializedBuildInfo }>) {
4646
return (
4747
<div>
4848
<Navbar routes={pageConfigs} />
4949
<div className="absolute min-h-screen min-w-full bg-background transition duration-1000">
5050
{children}
5151
<div className="absolute bottom-0 left-0 w-full">
52-
<BuildStamp buildInfo={buildInfo} />
52+
<BuildStamp serializedBuildInfo={serializedBuildInfo} />
5353
</div>
5454
</div>
5555
<Toaster />

lib/buildInfo.ts

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
export function computeGithubURLs(commit: BuildCommitInfo) {
1+
import {
2+
fromISODateString,
3+
ISODateString,
4+
Serialized,
5+
toISODateString,
6+
} from "./utils";
7+
8+
export function computeGithubURLs(buildInfo: BuildInfo) {
29
return {
3-
repoURL: `https://github.com/michaelfortunato/${commit.repo}`,
4-
commitURL: `https://github.com/michaelfortunato/${commit.repo}/commit/${commit.hash}`,
5-
branchURL: `https://github.com/michaelfortunato/${commit.repo}/tree/${commit.branch}`,
10+
repoURL: `https://github.com/michaelfortunato/personal-website`,
11+
commitURL: `https://github.com/michaelfortunato/personal-website/commit/${buildInfo.buildCommitEntry.commitHash}`,
12+
branchURL: `https://github.com/michaelfortunato/personal-website/tree/${buildInfo.branch}`,
613
};
714
}
815

@@ -18,14 +25,56 @@ export type CommitEntry = {
1825
message: string;
1926
};
2027

28+
export type SerializedCommitEntry = Serialized<CommitEntry>;
29+
30+
export function serializeCommitEntry(
31+
entry: CommitEntry,
32+
): SerializedCommitEntry {
33+
return {
34+
...entry,
35+
timestamp: toISODateString(entry.timestamp),
36+
};
37+
}
38+
39+
export function deserializeCommitEntry(
40+
entry: SerializedCommitEntry,
41+
): CommitEntry {
42+
return {
43+
...entry,
44+
timestamp: fromISODateString(entry.timestamp),
45+
};
46+
}
47+
2148
/// Define the expected structure of the Commit information.
22-
export type BuildCommitInfo = {
23-
repo: string;
24-
hash: string;
49+
///@deprecated use CommitEntry instead
50+
export type BuildInfo = {
2551
branch: string;
52+
buildTimestamp: Date;
53+
buildCommitEntry: CommitEntry;
2654
};
2755

28-
export type BuildInfo = {
29-
commitInfo: BuildCommitInfo;
30-
buildTimestamp: string;
56+
export type SerializedBuildInfo = {
57+
branch: string;
58+
buildTimestamp: string | ISODateString;
59+
buildCommitEntry: SerializedCommitEntry;
3160
};
61+
62+
export function serializeBuildInfo(buildInfo: BuildInfo): SerializedBuildInfo {
63+
return {
64+
...buildInfo,
65+
buildCommitEntry: {
66+
...buildInfo.buildCommitEntry,
67+
timestamp: toISODateString(buildInfo.buildCommitEntry.timestamp),
68+
},
69+
buildTimestamp: buildInfo.buildTimestamp.toLocaleDateString("en-US", {
70+
month: "short",
71+
day: "numeric",
72+
year: "numeric",
73+
hour: "numeric",
74+
minute: "2-digit",
75+
hour12: true,
76+
timeZoneName: "short",
77+
timeZone: "America/Chicago",
78+
}),
79+
};
80+
}

lib/posts.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { CommitEntry } from "@/lib/buildInfo";
1+
import {
2+
CommitEntry,
3+
deserializeCommitEntry,
4+
serializeCommitEntry,
5+
} from "@/lib/buildInfo";
26
import { fromISODateString, Serialized, toISODateString } from "@/lib/utils";
37

48
type MetadataArgs = {
@@ -52,20 +56,6 @@ export type Post = {
5256
export type SerializedPostMetadata = Serialized<PostMetadata>;
5357
export type SerializedPost = Serialized<Post>;
5458

55-
function serializeCommitEntry(entry: CommitEntry): Serialized<CommitEntry> {
56-
return {
57-
...entry,
58-
timestamp: toISODateString(entry.timestamp),
59-
};
60-
}
61-
62-
function deserializeCommitEntry(entry: Serialized<CommitEntry>): CommitEntry {
63-
return {
64-
...entry,
65-
timestamp: fromISODateString(entry.timestamp),
66-
};
67-
}
68-
6959
export function serializePostMetadata(
7060
metadata: PostMetadata,
7161
): SerializedPostMetadata {

lib/server-only/buildInfo.ts

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,36 @@
11
import { execSync, execFile } from "child_process";
22
import { promisify } from "util";
3-
import type { BuildInfo, BuildCommitInfo } from "@/lib/buildInfo";
3+
import { BuildInfo, CommitEntry } from "@/lib/buildInfo";
4+
import { fromISODateString, Serialized, toISODateString } from "../utils";
45
const execFileAsync = promisify(execFile);
56

67
export async function getBuildInfo(): Promise<BuildInfo> {
7-
return {
8-
commitInfo: await getBuildCommitInfo(),
9-
buildTimestamp: new Date().toLocaleDateString("en-US", {
10-
month: "short",
11-
day: "numeric",
12-
year: "numeric",
13-
hour: "numeric",
14-
minute: "2-digit",
15-
hour12: true,
16-
timeZoneName: "short",
17-
timeZone: "America/Chicago",
18-
}),
19-
};
8+
// NOTE: We assume our build environment has our git repo
9+
// and git history configured, which getCommitEntryForFile already assumes.
10+
// So lets just use the git cli to get the info.
11+
const branch =
12+
launchShellCmd("git branch --show-current")?.toString().trim() || null;
13+
if (branch == null) {
14+
throw "Could not compute branch for the build build, are you sure you set up git";
15+
}
16+
const buildCommitEntry = getCommitEntry(null, true);
17+
if (buildCommitEntry == null) {
18+
throw "Could not compute commit entry for build, are you sure you set up git";
19+
}
20+
const buildTimestamp = new Date();
21+
return { branch, buildTimestamp, buildCommitEntry };
2022
}
2123

22-
export function getCommitEntryForFile(filepath: string, head: boolean = true) {
24+
export function getCommitEntry(
25+
forFilepath: string | null = null,
26+
head: boolean = true,
27+
): CommitEntry | null {
2328
// Prior style for reference: "%H - %an, %at : %s"
2429
// Example: "8fd2212f... - Michael Fortunato, 1739958235 : tighten static props typing"
2530
const commitEntryFormat = "%H%x1f%an%x1f%aI%x1f%s";
2631
const cmd = !head
27-
? `git log --reverse --pretty=format:"${commitEntryFormat}" -- ${filepath} | head -1`
28-
: `git log -1 --pretty=format:"${commitEntryFormat}" -- ${filepath}`;
32+
? `git log --reverse --pretty=format:"${commitEntryFormat}" ${forFilepath != null ? "-- " + forFilepath : ""} | head -1`
33+
: `git log -1 --pretty=format:"${commitEntryFormat}" ${forFilepath != null ? "-- " + forFilepath : ""}`;
2934
const commitEntry = launchShellCmd(cmd)?.toString().trim();
3035
if (commitEntry == null) return null;
3136
const [commitHash, author, authorDateISO, message] =
@@ -37,6 +42,7 @@ export function getCommitEntryForFile(filepath: string, head: boolean = true) {
3742
if (Number.isNaN(timestamp.valueOf())) {
3843
return null;
3944
}
45+
4046
return {
4147
commitHash,
4248
get shortCommitHash() {
@@ -60,28 +66,6 @@ export function isDirty(filepath?: string) {
6066
}
6167
}
6268

63-
/// Returns the commit info for this build
64-
async function getBuildCommitInfo(): Promise<BuildCommitInfo> {
65-
// NOTE: We assume our build environment has our git repo
66-
// and git history configured, which getCommitEntryForFile already assumes.
67-
// So lets just use the git cli to get the info.
68-
const branch = launchShellCmd("git branch --show-current")?.toString().trim();
69-
if (!branch)
70-
throw "Could not compute build branch using git cli. Are you sure the build environment has git set up?";
71-
const hash = launchShellCmd(`git log -1 --pretty=format:"%H"`)
72-
?.toString()
73-
.trim();
74-
if (!hash)
75-
throw "Could not compute build commit hash using git cli. Are you sure the build environment has git set up?";
76-
const repo = "personal-website"; // This should never change.
77-
78-
return {
79-
repo,
80-
hash,
81-
branch,
82-
};
83-
}
84-
8569
let _gitDir: string | null = null;
8670
export async function getGitDir(): Promise<string> {
8771
if (_gitDir) return _gitDir;

lib/server-only/posts.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@ import * as cheerio from "cheerio";
55
const execFileAsync = promisify(execFile);
66
import { readdir } from "fs/promises";
77

8-
import {
9-
getCommitEntryForFile,
10-
getGitDir,
11-
isDirty as isDirtyFunc,
12-
} from "./buildInfo";
8+
import { getCommitEntry, getGitDir, isDirty as isDirtyFunc } from "./buildInfo";
139
import { PostMetadata, Post } from "@/lib/posts";
1410
import { parseTimestamp } from "@/lib/utils";
1511

1612
export function getCommitInfoForFileOrFallback(filepath: string) {
17-
const firstCommit = getCommitEntryForFile(filepath, false);
18-
const currentCommit = getCommitEntryForFile(filepath, true);
13+
const firstCommit = getCommitEntry(filepath, false);
14+
const currentCommit = getCommitEntry(filepath, true);
1915
const isDirty = isDirtyFunc(filepath);
2016
if (firstCommit && currentCommit) {
2117
return { isDirty, firstCommit, currentCommit };

lib/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export type ISODateString = string & { readonly __isoDateStringBrand: true };
1010
type Primitive = string | number | boolean | null | undefined;
1111

1212
export type Serialized<T> = T extends Date
13-
? ISODateString
13+
? ISODateString | string
1414
: T extends Primitive
1515
? T
1616
: T extends readonly (infer U)[]

0 commit comments

Comments
 (0)