Compare commits
5 Commits
af368eeee0
...
deploy/stg
| Author | SHA1 | Date | |
|---|---|---|---|
| 09c7fd8f3a | |||
| 656ffcc561 | |||
| 76ffa662c5 | |||
| 46423409fd | |||
| 2edf5e9b11 |
@@ -59,9 +59,16 @@ COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/prisma ./prisma
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/next.config.* ./
|
||||
COPY --chmod=755 docker-entrypoint.sh ./docker-entrypoint.sh
|
||||
|
||||
# Create uploads directory with proper permissions
|
||||
RUN mkdir -p /app/uploads && chown nextjs:nodejs /app/uploads
|
||||
|
||||
USER nextjs
|
||||
|
||||
# Persistent storage for uploaded files
|
||||
VOLUME ["/app/uploads"]
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["bun", "start"]
|
||||
CMD ["/app/docker-entrypoint.sh"]
|
||||
19
QWEN.md
19
QWEN.md
@@ -232,21 +232,4 @@ Common issues and solutions:
|
||||
6. Verify responsive design on different screen sizes
|
||||
|
||||
## Qwen Added Memories
|
||||
- **GitHub Workflow Execution**: Project ini memiliki 3 workflow GitHub Action:
|
||||
1. `publish.yml` - Build & push Docker image ke GHCR (manual trigger, butuh input: stack_env + tag)
|
||||
2. `re-pull.yml` - Re-pull Docker image di Portainer (manual trigger, butuh input: stack_name + stack_env)
|
||||
3. `docker-publish.yml` - Auto build & push saat ada tag versi v*
|
||||
|
||||
Workflow bisa dijalankan via GitHub CLI: `gh workflow run <nama.yml> -f param=value --ref branch`
|
||||
|
||||
Setelah commit ke branch deployment (dev/stg/prod), otomatis trigger workflow publish + re-pull untuk deploy ke server.
|
||||
- **Deployment Workflow Sistematis**:
|
||||
1. **Version Bump** - Update `version` di `package.json` sebelum deploy (ikuti semver: major.minor.patch)
|
||||
2. **Commit** - Commit perubahan + version bump dengan pesan yang jelas
|
||||
3. **Push ke Branch** - Push ke branch target (biasanya `stg` untuk staging atau `prod` untuk production)
|
||||
4. **Trigger Publish** - Jalankan `gh workflow run publish.yml --ref <branch> -f stack_env=<env> -f tag=<version>`
|
||||
5. **Trigger Re-Pull** - Jalankan `gh workflow run re-pull.yml -f stack_name=desa-darmasaba -f stack_env=<env>`
|
||||
6. **Verifikasi** - Cek workflow berhasil dan aplikasi berjalan
|
||||
|
||||
Branch deployment: `stg` (staging) atau `prod` (production)
|
||||
Version format di package.json: `"version": "major.minor.patch"`
|
||||
- **GitHub Workflows**: Project ini memiliki workflow GitHub Action untuk deployment. User akan menangani workflow secara manual di GitHub.
|
||||
|
||||
13
docker-entrypoint.sh
Normal file
13
docker-entrypoint.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🔄 Running database migrations..."
|
||||
cd /app
|
||||
bunx prisma migrate deploy || {
|
||||
echo "❌ Migration failed!"
|
||||
exit 1
|
||||
}
|
||||
echo "✅ Migrations completed successfully"
|
||||
|
||||
echo "🚀 Starting application..."
|
||||
exec bun start
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "desa-darmasaba",
|
||||
"version": "0.1.6",
|
||||
"version": "0.1.8",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "DataBanjar" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"penduduk" INTEGER NOT NULL,
|
||||
"kk" INTEGER NOT NULL,
|
||||
"miskin" INTEGER NOT NULL,
|
||||
"tahun" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "DataBanjar_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "DistribusiAgama" (
|
||||
"id" TEXT NOT NULL,
|
||||
"agama" TEXT NOT NULL,
|
||||
"jumlah" INTEGER NOT NULL,
|
||||
"tahun" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "DistribusiAgama_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "DistribusiUmur" (
|
||||
"id" TEXT NOT NULL,
|
||||
"rentangUmur" TEXT NOT NULL,
|
||||
"jumlah" INTEGER NOT NULL,
|
||||
"tahun" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "DistribusiUmur_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "MigrasiPenduduk" (
|
||||
"id" TEXT NOT NULL,
|
||||
"nama" TEXT NOT NULL,
|
||||
"jenis" "JenisMigrasi" NOT NULL,
|
||||
"tanggal" TIMESTAMP(3) NOT NULL,
|
||||
"asal" TEXT,
|
||||
"tujuan" TEXT,
|
||||
"alasan" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "MigrasiPenduduk_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "DinamikaPenduduk" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tahun" INTEGER NOT NULL,
|
||||
"kelahiran" INTEGER NOT NULL,
|
||||
"kematian" INTEGER NOT NULL,
|
||||
"masuk" INTEGER NOT NULL,
|
||||
"keluar" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
CONSTRAINT "DinamikaPenduduk_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DataBanjar_tahun_idx" ON "DataBanjar"("tahun");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DataBanjar_isActive_idx" ON "DataBanjar"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DistribusiAgama_tahun_idx" ON "DistribusiAgama"("tahun");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DistribusiAgama_isActive_idx" ON "DistribusiAgama"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DistribusiUmur_tahun_idx" ON "DistribusiUmur"("tahun");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DistribusiUmur_isActive_idx" ON "DistribusiUmur"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "MigrasiPenduduk_tanggal_idx" ON "MigrasiPenduduk"("tanggal");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "MigrasiPenduduk_isActive_idx" ON "MigrasiPenduduk"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DinamikaPenduduk_tahun_idx" ON "DinamikaPenduduk"("tahun");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DinamikaPenduduk_isActive_idx" ON "DinamikaPenduduk"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "DinamikaPenduduk_tahun_key" ON "DinamikaPenduduk"("tahun");
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "JenisMigrasi" AS ENUM ('MASUK', 'KELUAR');
|
||||
@@ -79,7 +79,7 @@ const fileStorageCreate = async (context: Context) => {
|
||||
data: {
|
||||
name: finalName,
|
||||
realName: file.name,
|
||||
path: rootPath,
|
||||
path: pathName, // Store relative path (e.g., "images", "audio", "documents")
|
||||
mimeType: finalMimeType,
|
||||
category,
|
||||
link: `/api/fileStorage/findUnique/${finalName}`,
|
||||
|
||||
@@ -36,7 +36,7 @@ const fileStorageDelete = async (context: Context) => {
|
||||
};
|
||||
}
|
||||
|
||||
const filePath = path.join(file.path, file.name);
|
||||
const filePath = path.join(UPLOAD_DIR, file.path, file.name);
|
||||
|
||||
try {
|
||||
// Hapus file dari filesystem
|
||||
|
||||
@@ -3,6 +3,8 @@ import { Context } from "elysia";
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
|
||||
const UPLOAD_DIR = process.env.WIBU_UPLOAD_DIR;
|
||||
|
||||
const fileStorageFindUnique = async (context: Context) => {
|
||||
const { name } = context.params;
|
||||
|
||||
@@ -20,9 +22,17 @@ const fileStorageFindUnique = async (context: Context) => {
|
||||
};
|
||||
}
|
||||
|
||||
if (!UPLOAD_DIR) {
|
||||
context.set.status = "Internal Server Error";
|
||||
return {
|
||||
status: 500,
|
||||
message: "UPLOAD_DIR is not defined",
|
||||
};
|
||||
}
|
||||
|
||||
console.log(data);
|
||||
|
||||
const file = await fs.readFile(path.join(data.path, data.name));
|
||||
const file = await fs.readFile(path.join(UPLOAD_DIR, data.path, data.name));
|
||||
context.set.headers = {
|
||||
"Content-Type": data.mimeType,
|
||||
"Content-Length": file.length,
|
||||
|
||||
Reference in New Issue
Block a user