mirror of
https://github.com/nicotsx/zerobyte.git
synced 2026-01-25 13:48:18 -05:00
feat: show components versions (#297)
On hover on the Zerobyte version in the sidebar A card will appear to show the versions of the binaries (restic, rclone, shoutrrr)
This commit is contained in:
28
Dockerfile
28
Dockerfile
@@ -2,6 +2,14 @@ ARG BUN_VERSION="1.3.5"
|
||||
|
||||
FROM oven/bun:${BUN_VERSION}-alpine AS base
|
||||
|
||||
ARG RESTIC_VERSION="0.18.1"
|
||||
ARG RCLONE_VERSION="1.72.1"
|
||||
ARG SHOUTRRR_VERSION="0.13.1"
|
||||
|
||||
ENV VITE_RESTIC_VERSION=${RESTIC_VERSION} \
|
||||
VITE_RCLONE_VERSION=${RCLONE_VERSION} \
|
||||
VITE_SHOUTRRR_VERSION=${SHOUTRRR_VERSION}
|
||||
|
||||
RUN apk upgrade --no-cache && \
|
||||
apk add --no-cache davfs2=1.6.1-r2 openssh-client fuse3 sshfs tini
|
||||
|
||||
@@ -16,22 +24,19 @@ FROM base AS deps
|
||||
WORKDIR /deps
|
||||
|
||||
ARG TARGETARCH
|
||||
ARG RESTIC_VERSION="0.18.1"
|
||||
ARG RCLONE_VERSION="1.72.1"
|
||||
ARG SHOUTRRR_VERSION="0.13.1"
|
||||
ENV TARGETARCH=${TARGETARCH}
|
||||
|
||||
RUN apk add --no-cache curl bzip2 unzip tar
|
||||
|
||||
RUN echo "Building for ${TARGETARCH}"
|
||||
RUN if [ "${TARGETARCH}" = "arm64" ]; then \
|
||||
curl -L -o restic.bz2 "https://github.com/restic/restic/releases/download/v$RESTIC_VERSION/restic_$RESTIC_VERSION"_linux_arm64.bz2; \
|
||||
curl -L -o rclone.zip "https://github.com/rclone/rclone/releases/download/v$RCLONE_VERSION/rclone-v$RCLONE_VERSION-linux-arm64.zip"; \
|
||||
curl -L -o restic.bz2 "https://github.com/restic/restic/releases/download/v${RESTIC_VERSION}/restic_${RESTIC_VERSION}_linux_arm64.bz2"; \
|
||||
curl -L -o rclone.zip "https://github.com/rclone/rclone/releases/download/v${RCLONE_VERSION}/rclone-v${RCLONE_VERSION}-linux-arm64.zip"; \
|
||||
unzip rclone.zip; \
|
||||
curl -L -o shoutrrr.tar.gz "https://github.com/nicholas-fedor/shoutrrr/releases/download/v$SHOUTRRR_VERSION/shoutrrr_linux_arm64v8_${SHOUTRRR_VERSION}.tar.gz"; \
|
||||
curl -L -o shoutrrr.tar.gz "https://github.com/nicholas-fedor/shoutrrr/releases/download/v${SHOUTRRR_VERSION}/shoutrrr_linux_arm64v8_${SHOUTRRR_VERSION}.tar.gz"; \
|
||||
elif [ "${TARGETARCH}" = "amd64" ]; then \
|
||||
curl -L -o restic.bz2 "https://github.com/restic/restic/releases/download/v$RESTIC_VERSION/restic_$RESTIC_VERSION"_linux_amd64.bz2; \
|
||||
curl -L -o rclone.zip "https://github.com/rclone/rclone/releases/download/v$RCLONE_VERSION/rclone-v$RCLONE_VERSION-linux-amd64.zip"; \
|
||||
curl -L -o restic.bz2 "https://github.com/restic/restic/releases/download/v${RESTIC_VERSION}/restic_${RESTIC_VERSION}_linux_amd64.bz2"; \
|
||||
curl -L -o rclone.zip "https://github.com/rclone/rclone/releases/download/v${RCLONE_VERSION}/rclone-v${RCLONE_VERSION}-linux-amd64.zip"; \
|
||||
unzip rclone.zip; \
|
||||
curl -L -o shoutrrr.tar.gz "https://github.com/nicholas-fedor/shoutrrr/releases/download/v$SHOUTRRR_VERSION/shoutrrr_linux_amd64_${SHOUTRRR_VERSION}.tar.gz"; \
|
||||
fi
|
||||
@@ -47,6 +52,7 @@ FROM base AS development
|
||||
|
||||
ARG APP_VERSION=dev
|
||||
ENV APP_VERSION=${APP_VERSION}
|
||||
ENV VITE_APP_VERSION=${APP_VERSION}
|
||||
ENV NODE_ENV="development"
|
||||
|
||||
WORKDIR /app
|
||||
@@ -68,9 +74,10 @@ CMD ["bun", "run", "dev"]
|
||||
# ------------------------------
|
||||
# PRODUCTION
|
||||
# ------------------------------
|
||||
FROM oven/bun:${BUN_VERSION}-alpine AS builder
|
||||
FROM base AS builder
|
||||
|
||||
ARG APP_VERSION=dev
|
||||
ENV VITE_APP_VERSION=${APP_VERSION}
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -79,9 +86,6 @@ RUN bun install --frozen-lockfile
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN touch .env
|
||||
RUN echo "VITE_APP_VERSION=${APP_VERSION}" >> .env
|
||||
|
||||
RUN bun run build
|
||||
|
||||
FROM base AS production
|
||||
|
||||
@@ -14,8 +14,9 @@ import {
|
||||
useSidebar,
|
||||
} from "~/client/components/ui/sidebar";
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/client/components/ui/tooltip";
|
||||
import { HoverCard, HoverCardContent, HoverCardTrigger } from "~/client/components/ui/hover-card";
|
||||
import { cn } from "~/client/lib/utils";
|
||||
import { APP_VERSION } from "~/client/lib/version";
|
||||
import { APP_VERSION, RCLONE_VERSION, RESTIC_VERSION, SHOUTRRR_VERSION } from "~/client/lib/version";
|
||||
import { useUpdates } from "~/client/hooks/use-updates";
|
||||
import { ReleaseNotesDialog } from "./release-notes-dialog";
|
||||
|
||||
@@ -105,16 +106,32 @@ export function AppSidebar() {
|
||||
</SidebarContent>
|
||||
<SidebarFooter className="p-4 border-r border-t border-border/50">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<a
|
||||
href={releaseUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={cn("text-xs text-muted-foreground hover:text-foreground", {
|
||||
"opacity-0 w-0 overflow-hidden": state === "collapsed",
|
||||
})}
|
||||
>
|
||||
{displayVersion}
|
||||
</a>
|
||||
<HoverCard openDelay={200}>
|
||||
<HoverCardTrigger asChild>
|
||||
<a
|
||||
href={releaseUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={cn("text-xs text-muted-foreground hover:text-foreground", {
|
||||
"opacity-0 w-0 overflow-hidden": state === "collapsed",
|
||||
})}
|
||||
>
|
||||
{displayVersion}
|
||||
</a>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent side="top" align="start" className="w-fit p-3">
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-[11px]">
|
||||
<span className="text-muted-foreground">Restic:</span>
|
||||
<span className="font-mono">{RESTIC_VERSION}</span>
|
||||
<span className="text-muted-foreground">Rclone:</span>
|
||||
<span className="font-mono">{RCLONE_VERSION}</span>
|
||||
<span className="text-muted-foreground">Shoutrrr:</span>
|
||||
<span className="font-mono">{SHOUTRRR_VERSION}</span>
|
||||
</div>
|
||||
</div>
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
{hasUpdate && state !== "collapsed" && (
|
||||
<button
|
||||
type="button"
|
||||
|
||||
42
app/client/components/ui/hover-card.tsx
Normal file
42
app/client/components/ui/hover-card.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import * as React from "react"
|
||||
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
|
||||
|
||||
import { cn } from "~/client/lib/utils"
|
||||
|
||||
function HoverCard({
|
||||
...props
|
||||
}: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
|
||||
return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />
|
||||
}
|
||||
|
||||
function HoverCardTrigger({
|
||||
...props
|
||||
}: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
|
||||
return (
|
||||
<HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
function HoverCardContent({
|
||||
className,
|
||||
align = "center",
|
||||
sideOffset = 4,
|
||||
...props
|
||||
}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
|
||||
return (
|
||||
<HoverCardPrimitive.Portal data-slot="hover-card-portal">
|
||||
<HoverCardPrimitive.Content
|
||||
data-slot="hover-card-content"
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</HoverCardPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
||||
@@ -1 +1,4 @@
|
||||
export const APP_VERSION = import.meta.env.VITE_APP_VERSION || "dev";
|
||||
export const RESTIC_VERSION = import.meta.env.VITE_RESTIC_VERSION || "unknown";
|
||||
export const RCLONE_VERSION = import.meta.env.VITE_RCLONE_VERSION || "unknown";
|
||||
export const SHOUTRRR_VERSION = import.meta.env.VITE_SHOUTRRR_VERSION || "unknown";
|
||||
|
||||
@@ -24,7 +24,7 @@ export const CustomForm = ({ form }: Props) => {
|
||||
<FormDescription>
|
||||
Direct Shoutrrr URL for power users. See
|
||||
<a
|
||||
href="https://shoutrrr.nickfedor.com/v0.12.0/services/overview/"
|
||||
href="https://shoutrrr.nickfedor.com/latest/services/overview/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-strong-accent hover:underline"
|
||||
|
||||
3
bun.lock
3
bun.lock
@@ -15,6 +15,7 @@
|
||||
"@radix-ui/react-checkbox": "^1.3.3",
|
||||
"@radix-ui/react-collapsible": "^1.1.12",
|
||||
"@radix-ui/react-dialog": "^1.1.15",
|
||||
"@radix-ui/react-hover-card": "^1.1.15",
|
||||
"@radix-ui/react-label": "^2.1.8",
|
||||
"@radix-ui/react-progress": "^1.1.8",
|
||||
"@radix-ui/react-scroll-area": "^1.2.10",
|
||||
@@ -347,6 +348,8 @@
|
||||
|
||||
"@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
|
||||
|
||||
"@radix-ui/react-hover-card": ["@radix-ui/react-hover-card@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg=="],
|
||||
|
||||
"@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
|
||||
|
||||
"@radix-ui/react-label": ["@radix-ui/react-label@2.1.8", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A=="],
|
||||
|
||||
@@ -25,6 +25,8 @@ services:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: production
|
||||
args:
|
||||
- APP_VERSION=0.20.0
|
||||
container_name: zerobyte
|
||||
restart: unless-stopped
|
||||
devices:
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"@radix-ui/react-checkbox": "^1.3.3",
|
||||
"@radix-ui/react-collapsible": "^1.1.12",
|
||||
"@radix-ui/react-dialog": "^1.1.15",
|
||||
"@radix-ui/react-hover-card": "^1.1.15",
|
||||
"@radix-ui/react-label": "^2.1.8",
|
||||
"@radix-ui/react-progress": "^1.1.8",
|
||||
"@radix-ui/react-scroll-area": "^1.2.10",
|
||||
|
||||
Reference in New Issue
Block a user