From f8319b9ab51b5c56824addd4705991e0b9611009 Mon Sep 17 00:00:00 2001 From: bagasbanuna Date: Wed, 4 Mar 2026 14:12:12 +0800 Subject: [PATCH] Build with Github --- .github/workflows/publish.yml | 59 +++++++++ Dockerfile | 72 +++++++++++ next.config.js | 18 ++- scripts/postbuild.js | 6 +- src/app/api/mobile/user/route.ts | 24 ++-- zCoba.js | 204 ------------------------------- 6 files changed, 153 insertions(+), 230 deletions(-) create mode 100644 .github/workflows/publish.yml create mode 100644 Dockerfile delete mode 100644 zCoba.js diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..8adde642 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,59 @@ +name: Publish Docker to GHCR +on: + workflow_dispatch: + inputs: + tag: + description: "Image tag (e.g. v1.0.0)" + required: true + default: "latest" +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} +jobs: + publish: + name: Build & Push to GHCR + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Free disk space + run: | + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc + sudo rm -rf /opt/hostedtoolcache/CodeQL + sudo docker image prune --all --force + df -h + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Extract tag name + id: meta + run: echo "tag=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + platforms: linux/amd64 + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.tag }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..1207f778 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,72 @@ +# ============================== +# Stage 1: Builder +# ============================== +FROM node:20-bookworm-slim AS builder + +WORKDIR /app + +# Install system deps +RUN apt-get update && apt-get install -y --no-install-recommends \ + libc6 \ + git \ + openssl \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Copy dependency files first (for better caching) +COPY package.json package-lock.json* bun.lockb* ./ + +ENV SHARP_IGNORE_GLOBAL_LIBVIPS=1 +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NODE_OPTIONS="--max-old-space-size=4096" + +# 🔥 Skip postinstall scripts (fix onnxruntime error) +RUN npm install --legacy-peer-deps --ignore-scripts + +# Copy full source +COPY . . + +# Use .env.example as build env +# (Pastikan file ini ada di project) +RUN cp .env.example .env || true + +# Generate Prisma Client +ENV PRISMA_CLI_BINARY_TARGETS=debian-openssl-3.0.x +RUN npx prisma generate + +# Build Next.js +RUN npm run build + +# ============================== +# Stage 2: Runner (Production) +# ============================== +FROM node:20-bookworm-slim AS runner + +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + openssl \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +RUN groupadd --system --gid 1001 nodejs \ + && useradd --system --uid 1001 --gid nodejs nextjs + +# Copy standalone output +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static +COPY --from=builder /app/public ./public + +RUN chown -R nextjs:nodejs /app + +USER nextjs + +EXPOSE 3000 + +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +CMD ["node", "server.js"] \ No newline at end of file diff --git a/next.config.js b/next.config.js index 49565fa2..bd659ae2 100644 --- a/next.config.js +++ b/next.config.js @@ -1,25 +1,21 @@ /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: false, + output: "standalone", + eslint: { ignoreDuringBuilds: true }, + typescript: { ignoreBuildErrors: true }, experimental: { serverActions: true, - serverComponentsExternalPackages: ['@prisma/client'], - }, - output: "standalone", - staticPageGenerationTimeout: 180, // tingkatkan menjadi 3 menit - eslint: { - ignoreDuringBuilds: true, - }, - typescript: { - ignoreBuildErrors: true + serverComponentsExternalPackages: ["@prisma/client", ".prisma/client"], }, webpack: (config, { isServer }) => { if (isServer) { config.externals = config.externals || []; - config.externals.push('@prisma/client'); + config.externals.push("@prisma/client"); + config.externals.push(".prisma/client"); } return config; }, }; -module.exports = nextConfig; +module.exports = nextConfig; \ No newline at end of file diff --git a/scripts/postbuild.js b/scripts/postbuild.js index 170072d9..7f4ad634 100644 --- a/scripts/postbuild.js +++ b/scripts/postbuild.js @@ -43,9 +43,9 @@ const envSrc = path.join(__dirname, '../.env'); const envDest = path.join(standaloneDir, '.env'); if (fs.existsSync(envSrc)) { fs.copyFileSync(envSrc, envDest); - console.log('✓ .env file copied to standalone output'); + // console.log('✓ .env file copied to standalone output'); } else { - console.warn('⚠ .env file not found, skipping...'); + // console.warn('⚠ .env file not found, skipping...'); console.warn(' Pastikan DATABASE_URL di-set di system environment server!'); } @@ -54,7 +54,7 @@ const envLocalSrc = path.join(__dirname, '../.env-local'); const envLocalDest = path.join(standaloneDir, '.env-local'); if (fs.existsSync(envLocalSrc)) { fs.copyFileSync(envLocalSrc, envLocalDest); - console.log('✓ .env-local file copied to standalone output'); + // console.log('✓ .env-local file copied to standalone output'); } console.log('✅ Build script completed!'); \ No newline at end of file diff --git a/src/app/api/mobile/user/route.ts b/src/app/api/mobile/user/route.ts index e84faf27..7f442282 100644 --- a/src/app/api/mobile/user/route.ts +++ b/src/app/api/mobile/user/route.ts @@ -27,18 +27,18 @@ export async function GET(request: Request) { NOT: { Profile: null, }, - OR: [ - { - MasterUserRole: { - name: "User", - }, - }, - { - MasterUserRole: { - name: "Admin", - }, - }, - ], + // OR: [ + // { + // MasterUserRole: { + // name: "User", + // }, + // }, + // { + // MasterUserRole: { + // name: "Admin", + // }, + // }, + // ], }, include: { Profile: { diff --git a/zCoba.js b/zCoba.js deleted file mode 100644 index a2cbde8e..00000000 --- a/zCoba.js +++ /dev/null @@ -1,204 +0,0 @@ -const { PrismaClient } = require('@prisma/client') -const axios = require('axios') - -const prisma = new PrismaClient() - -// Daftar contoh data -const donationDataList = [ - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Bantuan Pendidikan Anak-anak Kurang Mampu", - "target": 50000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank Central Asia", - "rekening": "1234567890", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Kami ingin membantu anak-anak kurang mampu mendapatkan pendidikan yang layak.", - "cerita": "Pendidikan adalah hak dasar setiap anak. Namun, banyak anak-anak di pelosok negeri yang tidak bisa menikmati pendidikan karena keterbatasan ekonomi. Melalui kampanye ini, kami ingin mengumpulkan dana untuk membantu biaya pendidikan mereka.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj0" - } - }, - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Pembangunan Masjid di Desa Terpencil", - "target": 100000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank Mandiri", - "rekening": "0987654321", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Membangun masjid untuk masyarakat di daerah terpencil yang belum memiliki tempat ibadah.", - "cerita": "Di sebuah desa terpencil, masyarakat setiap hari harus berjalan jauh untuk bisa melaksanakan sholat berjamaah. Kami ingin membantu membangun masjid di tengah-tengah mereka agar ibadah bisa dilakukan dengan lebih tenang dan khusyuk.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj1" - } - }, - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Bantuan Korban Bencana Alam", - "target": 75000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank Rakyat Indonesia", - "rekening": "5678901234", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Membantu meringankan beban korban bencana alam berupa kebutuhan pokok dan kebutuhan darurat.", - "cerita": "Beberapa wilayah dilanda bencana banjir dan tanah longsor. Masyarakat kehilangan harta benda dan membutuhkan bantuan segera. Dana yang terkumpul akan digunakan untuk menyediakan makanan, obat-obatan, dan kebutuhan pokok lainnya.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj2" - } - }, - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Pengadaan Alat Medis Rumah Sakit", - "target": 150000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank Negara Indonesia", - "rekening": "4321098765", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Meningkatkan kualitas pelayanan kesehatan dengan menyediakan alat medis yang lebih baik.", - "cerita": "Rumah sakit daerah kekurangan alat medis untuk melayani pasien. Melalui donasi ini, kami ingin membantu pengadaan alat-alat medis penting seperti ventilator, USG, dan alat laboratorium untuk meningkatkan kualitas pelayanan kesehatan.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj3" - } - }, - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Program Beasiswa Mahasiswa Berprestasi", - "target": 80000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank Danamon", - "rekening": "1122334455", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Memberikan kesempatan kepada mahasiswa berprestasi untuk melanjutkan pendidikan tanpa beban biaya.", - "cerita": "Banyak mahasiswa berprestasi yang tidak mampu melanjutkan pendidikan karena keterbatasan biaya. Program beasiswa ini akan membantu mereka menyelesaikan kuliah hingga sarjana.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj4" - } - }, - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Pengadaan Air Bersih untuk Desa Kekeringan", - "target": 60000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank Permata", - "rekening": "6677889900", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Menyediakan akses air bersih bagi masyarakat yang tinggal di daerah rawan kekeringan.", - "cerita": "Beberapa desa mengalami kekeringan setiap tahunnya, membuat warga kesulitan mendapatkan air bersih. Kami ingin membangun sumur bor dan sistem distribusi air untuk membantu masyarakat setempat.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj5" - } - }, - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Pengobatan Gratis untuk Warga Tidak Mampu", - "target": 40000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank Panin", - "rekening": "9988776655", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Memberikan layanan kesehatan gratis bagi warga yang tidak mampu membayar biaya pengobatan.", - "cerita": "Banyak warga yang menunda pengobatan karena keterbatasan biaya. Melalui program ini, kami akan menyelenggarakan pengobatan gratis secara berkala di berbagai wilayah.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj6" - } - }, - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Pembangunan Taman Bacaan Masyarakat", - "target": 35000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank Mega", - "rekening": "1357924680", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Membangun taman bacaan untuk meningkatkan minat baca masyarakat di wilayah pedesaan.", - "cerita": "Minat baca masyarakat di pedesaan masih rendah karena keterbatasan akses buku. Taman bacaan ini akan menyediakan ribuan buku gratis dan ruang baca yang nyaman untuk semua usia.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj7" - } - }, - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Pelatihan Keterampilan untuk Pengangguran", - "target": 55000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank CIMB Niaga", - "rekening": "2468135790", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Memberikan pelatihan keterampilan untuk membantu pengangguran mendapatkan pekerjaan atau usaha mandiri.", - "cerita": "Angka pengangguran masih tinggi di beberapa wilayah. Program pelatihan ini akan memberikan keterampilan yang dibutuhkan pasar kerja, seperti menjahit, memasak, teknologi informasi, dan lainnya.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj8" - } - }, - { - "data": { - "authorId": "cmha6wb9w0001cfndwl9fcse6", - "title": "Renovasi Gedung Sekolah Rusak", - "target": 90000000, - "donasiMaster_DurasiId": 3, - "donasiMaster_KategoriId": 3, - "namaBank": "Bank OCBC NISP", - "rekening": "1029384756", - "imageId": "cm60j9q3m000xc9dc584v8rh8", - "pembukaan": "Merestrukturasi gedung sekolah yang rusak agar siswa bisa belajar dengan aman dan nyaman.", - "cerita": "Banyak gedung sekolah yang rusak parah dan membahayakan keselamatan siswa. Dana dari kampanye ini akan digunakan untuk renovasi dan perbaikan gedung sekolah yang membutuhkan.", - "imageCeritaId": "cm60j9q3m000xc9dc584v8rj9" - } - } -]; - -async function sendDonationData() { - const baseUrl = 'http://localhost:3000/api/mobile/donation'; // Sesuaikan dengan URL server Anda - const headers = { - 'Content-Type': 'application/json', - }; - - for (let i = 0; i < donationDataList.length; i++) { - try { - console.log(`Mengirim data ke-${i + 1}...`); - const response = await axios.post(`${baseUrl}?category=permanent`, donationDataList[i], { - headers: headers - }); - console.log(`Data ke-${i + 1} berhasil dikirim:`, response.data); - } catch (error) { - console.error(`Error saat mengirim data ke-${i + 1}:`, error.response?.data || error.message); - } - } -} - -async function main() { - // Menjalankan fungsi untuk mengirim data donasi - await sendDonationData(); - - // Fungsi asli untuk update notifikasi - const result = await prisma.notifikasi.updateMany({ - where: { - recipientId: 'cmha7p6yc0000cfoe5w2e7gdr', - }, - data: { - isRead: false, - readAt: null, - }, - }) - - console.log(`✅ Rows affected: ${result.count}`) -} - -main() - .catch((err) => { - console.error('❌ Error:', err) - process.exit(1) - }) - .finally(async () => { - await prisma.$disconnect() - })