Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/docker-build-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Docker Build and Publish

on:
push:
branches: [ "main" ]
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=sha,format=short
type=ref,event=branch
type=ref,event=tag

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
NEXT_TELEMETRY_DISABLED=1
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ COPY . .
# ENV NEXT_TELEMETRY_DISABLED=1

RUN \
if [ -f yarn.lock ]; then yarn run build; \
elif [ -f package-lock.json ]; then npm run build; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
if [ -f yarn.lock ]; then yarn run build --no-lint; \
elif [ -f package-lock.json ]; then npm run build --no-lint; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build --no-lint; \
else echo "Lockfile not found." && exit 1; \
fi

Expand Down
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,57 @@ docker run -p 3000:3000 --env-file .env nextjs-gemini-image-editing

Open [http://localhost:3000](http://localhost:3000) with your browser to see the application.

### GitHub Actions Automated Build

This project is configured with GitHub Actions workflow to automatically build Docker images and publish them to GitHub Container Registry (GHCR).

#### Triggers

The workflow is triggered by:
- Push to the `main` branch
- Manual workflow dispatch

#### Features

1. Checkout repository code
2. Set up Docker Buildx
3. Log in to GitHub Container Registry
4. Extract Docker image metadata (tags, labels)
5. Build and push Docker image to GitHub Container Registry

#### Image Tags

Automatically generated tags include:
- `latest` (only for default branch)
- Short SHA commit hash
- Branch name
- Tag name (if any)

#### Permissions

The workflow requires the following permissions:
- `contents: read` - Read repository contents
- `packages: write` - Write to GitHub Packages (for publishing Docker images)

#### Usage

1. Ensure GitHub Actions is enabled for your repository
2. Ensure GitHub Packages is enabled for your repository
3. Push code to the `main` branch or manually trigger the workflow
4. After the build completes, view the published Docker image on the GitHub Packages page

#### Pull Image

```bash
docker pull ghcr.io/[username]/[repository]:latest
```

#### Run Container

```bash
docker run -p 3000:3000 -e GEMINI_API_KEY=your_google_api_key ghcr.io/[username]/[repository]:latest
```

## Technologies Used

- [Next.js](https://nextjs.org/) - React framework for the web application
Expand Down
2 changes: 2 additions & 0 deletions components/ImageResultDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export function ImageResultDisplay({
</div>

<div className="rounded-lg overflow-hidden bg-muted p-2">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={imageUrl}
alt="Generated"
Expand Down Expand Up @@ -90,6 +91,7 @@ export function ImageResultDisplay({
{part.text && <p className="text-sm">{part.text}</p>}
{part.image && (
<div className="mt-2 overflow-hidden rounded-md">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={part.image}
alt={`${item.role} image`}
Expand Down
15 changes: 9 additions & 6 deletions components/ImageUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useCallback, useState, useEffect } from "react";
import { useDropzone } from "react-dropzone";
import { Button } from "./ui/button";
import { Upload as UploadIcon, Image as ImageIcon, X } from "lucide-react";
import Image from "next/image";

interface ImageUploadProps {
onImageSelect: (imageData: string) => void;
currentImage: string | null;
Expand Down Expand Up @@ -119,11 +119,14 @@ export function ImageUpload({ onImageSelect, currentImage }: ImageUploadProps) {
</Button>
</div>
<div className="w-full overflow-hidden rounded-md">
<img
src={currentImage}
alt="Selected"
className="w-full h-auto object-contain"
/>
<div className="relative w-full aspect-[4/3]">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={currentImage}
alt="Selected"
className="w-full h-auto object-contain"
/>
</div>
</div>
</div>
)}
Expand Down