diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml new file mode 100644 index 0000000..8ed5dc4 --- /dev/null +++ b/.gitea/workflows/deploy.yaml @@ -0,0 +1,48 @@ +name: Build and Deploy + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Deploy to QNAP via SSH + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + port: ${{ secrets.PORT }} + script_stop_signal: true # Stop script on error + script: | + echo "🚀 Starting Deployment..." + + # 1. Update Code + echo "📂 Pulling latest code..." + cd /share/np-dms/app/source + git pull origin main + + # 2. Build Backend + echo "🏗ïļ Building Backend..." + docker build -f backend/Dockerfile -t lcbp3-backend:latest . + + # 3. Build Frontend + echo "🏗ïļ Building Frontend..." + docker build -f frontend/Dockerfile \ + --build-arg NEXT_PUBLIC_API_URL=https://backend.np-dms.work/api \ + -t lcbp3-frontend:latest . + + # 4. Update Containers + echo "🔄 Updating Containers..." + cd /share/np-dms/app + docker-compose up -d + + # 5. Cleanup + echo "ðŸ§đ Cleaning up unused images..." + docker image prune -f + + echo "✅ Deployment Complete!" diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 2baa3d0..c3fe4dd 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -65,7 +65,7 @@ RUN addgroup -g 1001 -S nextjs && \ # Copy standalone output from build COPY --from=build --chown=nextjs:nextjs /app/frontend/.next/standalone ./ -COPY --from=build --chown=nextjs:nextjs /app/frontend/.next/static ./.next/static +COPY --from=build --chown=nextjs:nextjs /app/frontend/.next/static ./frontend/.next/static USER nextjs @@ -74,4 +74,4 @@ EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=20s \ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1 -CMD ["node", "server.js"] +CMD ["node", "frontend/server.js"] diff --git a/lcbp3-frontend.tar b/lcbp3-frontend.tar index 74ac18d..51ad76a 100644 Binary files a/lcbp3-frontend.tar and b/lcbp3-frontend.tar differ diff --git a/specs/00-overview/00-01-quick-start.md b/specs/00-overview/00-01-quick-start.md index dbe8cc2..0c0a948 100644 --- a/specs/00-overview/00-01-quick-start.md +++ b/specs/00-overview/00-01-quick-start.md @@ -88,7 +88,7 @@ http://localhost:3000/api/docs **Default Admin Account:** - Username: `admin` -- Password: `Admin@123` (Change immediately!) +- Password: `Center2025` (Change immediately!) --- diff --git a/specs/07-database/lcbp3-v1.7.0-seed-basic.sql b/specs/07-database/lcbp3-v1.7.0-seed-basic.sql index a996eb0..06e74c6 100644 --- a/specs/07-database/lcbp3-v1.7.0-seed-basic.sql +++ b/specs/07-database/lcbp3-v1.7.0-seed-basic.sql @@ -5,7 +5,6 @@ VALUES (1, 'OWNER'), (4, 'CONTRACTOR'), (5, 'THIRD PARTY'), (6, 'GUEST'); - INSERT INTO organizations ( id, organization_code, @@ -80,7 +79,6 @@ VALUES (1, 'āļāļ—āļ—.', 'āļāļēāļĢāļ—āđˆāļēāđ€āļĢāļ·āļ­āđāļŦāđˆāļ‡āļ›āļĢāļ°āđ€ ), (31, 'EN', 'Third Party Environment', 5), (32, 'CAR', 'Third Party Fishery Care', 5); - -- Seed project INSERT INTO projects (project_code, project_name) VALUES ( @@ -107,7 +105,6 @@ VALUES ( 'LCBP3-EN', 'āđ‚āļ„āļĢāļ‡āļāļēāļĢāļžāļąāļ’āļ™āļēāļ—āđˆāļēāđ€āļĢāļ·āļ­āđāļŦāļĨāļĄāļ‰āļšāļąāļ‡ āļĢāļ°āļĒāļ°āļ—āļĩāđˆ 3 (āļŠāđˆāļ§āļ™āļ—āļĩāđˆ 4) āļ‡āļēāļ™āļāđˆāļ­āļŠāļĢāđ‰āļēāļ‡' ); - -- Seed contract -- āđƒāļŠāđ‰ Subquery āđ€āļžāļ·āđˆāļ­āļ”āļķāļ‡ project_id āļĄāļēāđ€āļŠāļ·āđˆāļ­āļĄāđ‚āļĒāļ‡ āļ—āļģāđƒāļŦāđ‰āđ„āļĄāđˆāļ•āđ‰āļ­āļ‡āļĄāļēāļ™āļąāđˆāļ‡āļˆāļąāļ”āļāļēāļĢ ID āļ”āđ‰āļ§āļĒāļ•āļąāļ§āđ€āļ­āļ‡ INSERT INTO contracts ( @@ -186,7 +183,6 @@ VALUES ( ), TRUE ); - -- Seed user -- Initial SUPER_ADMIN user INSERT INTO users ( @@ -239,7 +235,6 @@ VALUES ( NULL, 10 ); - -- ========================================================== -- Seed Roles (āļšāļ—āļšāļēāļ—āļžāļ·āđ‰āļ™āļāļēāļ™ 5 āļšāļ—āļšāļēāļ— āļ•āļēāļĄ Req 4.3) -- ========================================================== @@ -293,7 +288,6 @@ VALUES ( 'Contract', 'āļœāļđāđ‰āļ”āļđāđāļĨāļŠāļąāļāļāļē: āļˆāļąāļ”āļāļēāļĢāļŠāļĄāļēāļŠāļīāļāđƒāļ™āļŠāļąāļāļāļē, āļŠāļĢāđ‰āļēāļ‡ / āļˆāļąāļ”āļāļēāļĢāļ‚āđ‰āļ­āļĄāļđāļĨāļŦāļĨāļąāļāđ€āļ‰āļžāļēāļ°āļŠāļąāļāļāļē, āđāļĨāļ°āļ­āļ™āļļāļĄāļąāļ•āļīāđ€āļ­āļāļŠāļēāļĢāđƒāļ™āļŠāļąāļāļāļē' ); - -- ========================================================== -- Seed Role-Permissions Mapping (āļˆāļąāļšāļ„āļđāđˆāļŠāļīāļ—āļ˜āļīāđŒāđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™) -- ========================================================== @@ -304,7 +298,6 @@ VALUES ( -- ========================================================== -- SECTION 2: ROLE-PERMISSION MAPPINGS -- ========================================================== - -- Seed data for the 'user_assignments' table INSERT INTO user_assignments ( id, @@ -322,7 +315,6 @@ VALUES (1, 1, 1, NULL, NULL, NULL, NULL), (3, 3, 4, 41, NULL, NULL, 1), -- editor01: Editor role (role_id=4) at organization 41 (āļ„āļ„āļ‡.), assigned by superadmin (4, 4, 5, 10, NULL, NULL, 1); - -- viewer01: Viewer role (role_id=5) at organization 10 (āļŠāļ„āļ‰.03), assigned by superadmin -- ===================================================== -- == 4. āļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāđ‚āļĒāļ‡āđ‚āļ„āļĢāļ‡āļāļēāļĢāļāļąāļšāļ­āļ‡āļ„āđŒāļāļĢ (project_organizations) == @@ -348,7 +340,6 @@ WHERE organization_code IN ( 'EN', 'CAR' ); - -- āđ‚āļ„āļĢāļ‡āļāļēāļĢāļĒāđˆāļ­āļĒ (LCBP3C1) āļˆāļ°āļĄāļĩāđ€āļ‰āļžāļēāļ°āļ­āļ‡āļ„āđŒāļāļĢāļ—āļĩāđˆāđ€āļāļĩāđˆāļĒāļ§āļ‚āđ‰āļ­āļ‡ INSERT INTO project_organizations (project_id, organization_id) SELECT ( @@ -365,7 +356,6 @@ WHERE organization_code IN ( 'āļ„āļ„āļ‡.', 'āļœāļĢāļĄ.1 ' ); - -- āļ—āļģāđ€āļŠāđˆāļ™āđ€āļ”āļĩāļĒāļ§āļāļąāļ™āļŠāļģāļŦāļĢāļąāļšāđ‚āļ„āļĢāļ‡āļāļēāļĢāļ­āļ·āđˆāļ™āđ† (āļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡) INSERT INTO project_organizations (project_id, organization_id) SELECT ( @@ -382,7 +372,6 @@ WHERE organization_code IN ( 'āļ„āļ„āļ‡.', 'āļœāļĢāļĄ.2' ); - -- ===================================================== -- == 5. āļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāđ‚āļĒāļ‡āļŠāļąāļāļāļēāļāļąāļšāļ­āļ‡āļ„āđŒāļāļĢ (contract_organizations) == -- ===================================================== @@ -414,7 +403,6 @@ VALUES ( ), 'Designer' ); - -- āļŠāļąāļāļāļēāļ—āļĩāđˆāļ›āļĢāļķāļāļĐāļēāļ„āļ§āļšāļ„āļļāļĄāļ‡āļēāļ™ (PSLCBP3) INSERT INTO contract_organizations (contract_id, organization_id, role_in_contract) VALUES ( @@ -443,7 +431,6 @@ VALUES ( ), 'Consultant' ); - -- āļŠāļąāļāļāļēāļ‡āļēāļ™āļāđˆāļ­āļŠāļĢāđ‰āļēāļ‡ āļŠāđˆāļ§āļ™āļ—āļĩāđˆ 1 (LCBP3-C1) INSERT INTO contract_organizations (contract_id, organization_id, role_in_contract) VALUES ( @@ -472,7 +459,6 @@ VALUES ( ), 'Contractor' ); - -- āļŠāļąāļāļāļēāļ‡āļēāļ™āļāđˆāļ­āļŠāļĢāđ‰āļēāļ‡ āļŠāđˆāļ§āļ™āļ—āļĩāđˆ 2 (LCBP3-C2) INSERT INTO contract_organizations (contract_id, organization_id, role_in_contract) VALUES ( @@ -501,7 +487,6 @@ VALUES ( ), 'Contractor' ); - -- āļŠāļąāļāļāļēāļ•āļĢāļ§āļˆāļŠāļ­āļšāļŠāļīāđˆāļ‡āđāļ§āļ”āļĨāđ‰āļ­āļĄ (LCBP3-EN) INSERT INTO contract_organizations (contract_id, organization_id, role_in_contract) VALUES ( @@ -530,7 +515,6 @@ VALUES ( ), 'Consultant' ); - -- Seed correspondence_status INSERT INTO correspondence_status ( status_code, @@ -561,7 +545,6 @@ VALUES ('DRAFT', 'Draft', 10, 1), ('CCBDSN', 'Canceled by Designer', 92, 1), ('CCBCSC', 'Canceled by CSC', 93, 1), ('CCBCON', 'Canceled by Contractor', 94, 1); - -- Seed correspondence_types INSERT INTO correspondence_types (type_code, type_name, sort_order, is_active) VALUES ('RFA', 'Request for Approval', 1, 1), @@ -574,7 +557,6 @@ VALUES ('RFA', 'Request for Approval', 1, 1), ('MOM', 'Minutes of Meeting', 8, 1), ('NOTICE', 'Notice', 9, 1), ('OTHER', 'Other', 10, 1); - -- Seed rfa_types INSERT INTO rfa_types ( contract_id, @@ -1064,7 +1046,6 @@ SELECT id, 'āļĢāļēāļĒāļ‡āļēāļ™āļāļēāļĢāļāļķāļāļ›āļāļīāļšāļąāļ•āļī' FROM contracts WHERE contract_code = 'LCBP3-C2'; - -- Seed rfa_status_codes INSERT INTO rfa_status_codes ( status_code, @@ -1079,7 +1060,6 @@ VALUES ('DFT', 'Draft', 'āļ‰āļšāļąāļšāļĢāđˆāļēāļ‡', 1), ('ASB', 'AS - Built', 'āđāļšāļšāļāđˆāļ­āļŠāļĢāđ‰āļēāļ‡āļˆāļĢāļīāļ‡', 30), ('OBS', 'Obsolete', 'āđ„āļĄāđˆāđƒāļŠāđ‰āļ‡āļēāļ™', 80), ('CC', 'Canceled', 'āļĒāļāđ€āļĨāļīāļ', 99); - INSERT INTO rfa_approve_codes ( approve_code, approve_name, @@ -1094,14 +1074,12 @@ VALUES ('1A', 'Approved by Authority', 10, 1), ('3R', 'Revise and Resubmit', 32, 1), ('4X', 'Reject', 40, 1), ('5N', 'No Further Action', 50, 1); - -- Seed circulation_status_codes INSERT INTO circulation_status_codes (code, description, sort_order) VALUES ('OPEN', 'Open', 1), ('IN_REVIEW', 'In Review', 2), ('COMPLETED', 'āļ›Completed', 3), ('CANCELLED', 'Cancelled / Withdrawn', 9); - -- āļ•āļēāļĢāļēāļ‡ "āđāļĄāđˆ" āļ‚āļ­āļ‡ RFA (āļĄāļĩāļ„āļ§āļēāļĄāļŠāļąāļĄāļžāļąāļ™āļ˜āđŒ 1:N āļāļąāļš rfa_revisions) -- ========================================================== -- SEED DATA 6B.md (Disciplines, RFA Types, Sub Types) @@ -1365,7 +1343,6 @@ SELECT id, 'Other' FROM contracts WHERE contract_code = 'LCBP3-C1'; - -- LCBP3-C2 INSERT INTO disciplines ( contract_id, @@ -1610,7 +1587,6 @@ SELECT id, 'Others' FROM contracts WHERE contract_code = 'LCBP3-C2'; - -- 2. Seed āļ‚āđ‰āļ­āļĄāļđāļĨ Correspondence Sub Types (Mapping RFA Types āļāļąāļš Number) -- āđ€āļ™āļ·āđˆāļ­āļ‡āļˆāļēāļ sub_type_code āļ•āļĢāļ‡āļāļąāļš RFA Type Code āđāļ•āđˆ Req āļ•āđ‰āļ­āļ‡āļāļēāļĢ Mapping āđ€āļ›āđ‡āļ™ Number -- LCBP3-C1 @@ -1661,7 +1637,6 @@ FROM contracts c, correspondence_types ct WHERE c.contract_code = 'LCBP3-C1' AND ct.type_code = 'RFA'; - -- LCBP3-C2 INSERT INTO correspondence_sub_types ( contract_id, @@ -1709,7 +1684,6 @@ FROM contracts c, correspondence_types ct WHERE c.contract_code = 'LCBP3-C2' AND ct.type_code = 'RFA'; - -- LCBP3-C3 INSERT INTO correspondence_sub_types ( contract_id, @@ -1757,7 +1731,6 @@ FROM contracts c, correspondence_types ct WHERE c.contract_code = 'LCBP3-C3' AND ct.type_code = 'RFA'; - -- LCBP3-C4 INSERT INTO correspondence_sub_types ( contract_id, @@ -1805,7 +1778,6 @@ FROM contracts c, correspondence_types ct WHERE c.contract_code = 'LCBP3-C4' AND ct.type_code = 'RFA'; - INSERT INTO `correspondences` ( `id`, `correspondence_number`, @@ -1842,7 +1814,6 @@ VALUES ( 1, NULL ); - INSERT INTO `correspondence_revisions` ( `id`, `correspondence_id`, @@ -1881,7 +1852,6 @@ VALUES ( 1, NULL ); - INSERT INTO `rfas` ( `id`, `rfa_type_id`, @@ -1890,7 +1860,6 @@ INSERT INTO `rfas` ( `deleted_at` ) VALUES (2, 68, '2025-12-06 05:40:02', 1, NULL); - INSERT INTO `rfa_revisions` ( `id`, `rfa_id`, @@ -1931,7 +1900,6 @@ VALUES ( NULL, NULL ); - -- ========================================================== -- 20. Workflow Definitions (Unified Workflow Engine) -- ========================================================== @@ -2168,16 +2136,12 @@ VALUES ( NOW(), NOW() ); - INSERT INTO `document_number_formats` ( `id`, `project_id`, `correspondence_type_id`, `discipline_id`, - `format_template`, - `reset_sequence_yearly`, - `example_number`, - `padding_length`, + `format_string`, `reset_annually`, `is_active`, `description`, @@ -2191,9 +2155,6 @@ VALUES ( 0, '{ORG}-{RECIPIENT}-{SEQ:4}-{YEAR}', 1, - NULL, - 4, - 1, 1, NULL, '2025-12-16 09:33:36', @@ -2206,11 +2167,8 @@ VALUES ( 0, '{ORG}-{RECIPIENT}-{SEQ:4}-{YEAR}', 1, - NULL, - 4, - 1, 1, NULL, '2025-12-16 09:34:10', '2025-12-16 09:34:10' - ); + ); \ No newline at end of file diff --git a/specs/08-infrastructure/09_app_deployment.md b/specs/08-infrastructure/09_app_deployment.md index 23539be..ac70a91 100644 --- a/specs/08-infrastructure/09_app_deployment.md +++ b/specs/08-infrastructure/09_app_deployment.md @@ -183,6 +183,27 @@ docker load < /share/np-dms/app/lcbp3-frontend.tar --- +## 7. Automated Deployment via Gitea + +āļĢāļ°āļšāļšāļĢāļ­āļ‡āļĢāļąāļšāļāļēāļĢ Deploy āļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļīāļœāđˆāļēāļ™ **Gitea Actions** āđ€āļĄāļ·āđˆāļ­āļĄāļĩāļāļēāļĢ Push code āđ€āļ‚āđ‰āļēāļŠāļđāđˆ branch `main` + +### 7.1 Prerequisites +1. **Enable Actions:** āđ€āļ›āļīāļ”āđƒāļŠāđ‰āļ‡āļēāļ™ Gitea Actions āđƒāļ™ Repository Settings +2. **Secrets:** āļ•āđ‰āļ­āļ‡āļāļģāļŦāļ™āļ” Secrets āļ•āđˆāļ­āđ„āļ›āļ™āļĩāđ‰āđƒāļ™ Repository Settings -> Actions -> Secrets: + - `HOST`: IP Address āļ‚āļ­āļ‡ QNAP Server (e.g. `192.168.10.8`) + - `USERNAME`: SSH Username (e.g. `admin`) + - `PASSWORD`: SSH Password (āļŦāļĢāļ·āļ­āđƒāļŠāđ‰ `KEY` āļŠāļģāļŦāļĢāļąāļš Private Key) + - `PORT`: SSH Port (Default: `22`) + +### 7.2 Workflow Process +āđ€āļĄāļ·āđˆāļ­ Pipeline āļ—āļģāļ‡āļēāļ™ āļˆāļ°āļ”āļģāđ€āļ™āļīāļ™āļāļēāļĢāļ”āļąāļ‡āļ™āļĩāđ‰āļœāđˆāļēāļ™ SSH: +1. `git pull`: āļ”āļķāļ‡ Code āļĨāđˆāļēāļŠāļļāļ”āļ—āļĩāđˆ `/share/np-dms/app/source` +2. `docker build`: Build images āđƒāļŦāļĄāđˆāļŠāļģāļŦāļĢāļąāļš Backend āđāļĨāļ° Frontend +3. `docker-compose up -d`: Recreate containers āļ”āđ‰āļ§āļĒ image āđƒāļŦāļĄāđˆ +4. `docker image prune`: āļĨāļš Image āđ€āļāđˆāļēāļ—āļĩāđˆāđ„āļĄāđˆāđ„āļ”āđ‰āđƒāļŠāđ‰āđ€āļžāļ·āđˆāļ­āļ›āļĢāļ°āļŦāļĒāļąāļ”āļžāļ·āđ‰āļ™āļ—āļĩāđˆ + +--- + ## ðŸ“Ķ Resource Summary | Service | Image | CPU Limit | Memory Limit | Port |