diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml new file mode 100644 index 0000000..4375caf --- /dev/null +++ b/.forgejo/workflows/deploy.yml @@ -0,0 +1,40 @@ +name: Build & Deploy to Hostverge FTP + +on: + push: + branches: + - main + - master + workflow_dispatch: + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + - name: šŸ“„ Checkout repository + uses: actions/checkout@v4 + + - name: 🟢 Setup Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: šŸ“¦ Install dependencies + run: npm ci || npm install + + - name: šŸ› ļø Build application + env: + VITE_NCB_INSTANCE: ${{ secrets.VITE_NCB_INSTANCE || '54770_uwu_finances' }} + VITE_NCB_SECRET_KEY: ${{ secrets.VITE_NCB_SECRET_KEY || 'sk_live_0dydoaq1kib4f23ou6' }} + VITE_NCB_DATA_API_URL: ${{ secrets.VITE_NCB_DATA_API_URL || 'https://eu-api.nocodebackend.com' }} + run: npm run build + + - name: šŸš€ Sync files to Hostverge via FTP + uses: SamKirkland/FTP-Deploy-Action@v4.3.5 + with: + server: ${{ secrets.FTP_SERVER || 'ka-el.fr' }} + username: ${{ secrets.FTP_USERNAME || 'antigravity@ka-el.fr' }} + password: ${{ secrets.FTP_PASSWORD || 'dxr1yaor4i' }} + local-dir: ./dist/ + server-dir: ./ + dangerous-clean-slate: false diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..4375caf --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,40 @@ +name: Build & Deploy to Hostverge FTP + +on: + push: + branches: + - main + - master + workflow_dispatch: + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + - name: šŸ“„ Checkout repository + uses: actions/checkout@v4 + + - name: 🟢 Setup Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: šŸ“¦ Install dependencies + run: npm ci || npm install + + - name: šŸ› ļø Build application + env: + VITE_NCB_INSTANCE: ${{ secrets.VITE_NCB_INSTANCE || '54770_uwu_finances' }} + VITE_NCB_SECRET_KEY: ${{ secrets.VITE_NCB_SECRET_KEY || 'sk_live_0dydoaq1kib4f23ou6' }} + VITE_NCB_DATA_API_URL: ${{ secrets.VITE_NCB_DATA_API_URL || 'https://eu-api.nocodebackend.com' }} + run: npm run build + + - name: šŸš€ Sync files to Hostverge via FTP + uses: SamKirkland/FTP-Deploy-Action@v4.3.5 + with: + server: ${{ secrets.FTP_SERVER || 'ka-el.fr' }} + username: ${{ secrets.FTP_USERNAME || 'antigravity@ka-el.fr' }} + password: ${{ secrets.FTP_PASSWORD || 'dxr1yaor4i' }} + local-dir: ./dist/ + server-dir: ./ + dangerous-clean-slate: false diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..cb2cd07 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,41 @@ +name: Build & Deploy to Hostverge FTP + +on: + push: + branches: + - main + - master + workflow_dispatch: + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + steps: + - name: šŸ“„ Checkout repository + uses: actions/checkout@v4 + + - name: 🟢 Setup Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + + - name: šŸ“¦ Install dependencies + run: npm ci || npm install + + - name: šŸ› ļø Build application + env: + VITE_NCB_INSTANCE: ${{ secrets.VITE_NCB_INSTANCE || '54770_uwu_finances' }} + VITE_NCB_SECRET_KEY: ${{ secrets.VITE_NCB_SECRET_KEY || 'sk_live_0dydoaq1kib4f23ou6' }} + VITE_NCB_DATA_API_URL: ${{ secrets.VITE_NCB_DATA_API_URL || 'https://eu-api.nocodebackend.com' }} + run: npm run build + + - name: šŸš€ Sync files to Hostverge via FTP + uses: SamKirkland/FTP-Deploy-Action@v4.3.5 + with: + server: ${{ secrets.FTP_SERVER || 'ka-el.fr' }} + username: ${{ secrets.FTP_USERNAME || 'antigravity@ka-el.fr' }} + password: ${{ secrets.FTP_PASSWORD || 'dxr1yaor4i' }} + local-dir: ./dist/ + server-dir: ./ + dangerous-clean-slate: false diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..1315826 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,34 @@ +image: node:20 + +stages: + - build + - deploy + +build_app: + stage: build + variables: + VITE_NCB_INSTANCE: "54770_uwu_finances" + VITE_NCB_SECRET_KEY: "sk_live_0dydoaq1kib4f23ou6" + VITE_NCB_DATA_API_URL: "https://eu-api.nocodebackend.com" + script: + - npm ci || npm install + - npm run build + artifacts: + paths: + - dist/ + expire_in: 1 hour + only: + - main + - master + +deploy_ftp: + stage: deploy + dependencies: + - build_app + before_script: + - apt-get update -qq && apt-get install -y -qq lftp + script: + - lftp -e "set ftp:ssl-allow no; open ka-el.fr; user antigravity@ka-el.fr dxr1yaor4i; mirror -R dist/ /; quit" + only: + - main + - master diff --git a/package-lock.json b/package-lock.json index 1e338a5..1d6cdd2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,8 @@ "@types/react-dom": "^19.2.7", "@vitejs/plugin-react": "^6.1.1", "autoprefixer": "^10.6.1", + "basic-ftp": "^6.2.1", + "dotenv": "^18.0.4", "oxlint": "^1.81.0", "postcss": "^8.5.28", "tailwindcss": "^4.3.3", @@ -1394,6 +1396,16 @@ "node": ">=6.0.0" } }, + "node_modules/basic-ftp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-6.2.1.tgz", + "integrity": "sha512-bK67isD+lKq46AU8vNtjvMaT2ZqAOAmNCbxUHlFBRD4k15NWxyEjmaKtZPlgce58So4BNTjITGQOVTjL9y0ECA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/browserslist": { "version": "4.29.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.1.tgz", @@ -1611,6 +1623,22 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-18.0.4.tgz", + "integrity": "sha512-jGt9uI5BIxpVO15kvy+iEFqNAwxYClKWnkptLjSNPnFLC003Imd0ofr3aEVsbpHdSBdSsbcApNIlz4nbyGMwdA==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "dotenv": "dist/index.cjs" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.439", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.439.tgz", diff --git a/package.json b/package.json index 70693ed..1807dff 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "dev": "vite", "build": "tsc -b && vite build", + "deploy": "node scripts/deploy-ftp.cjs", "lint": "oxlint", "preview": "vite preview" }, @@ -28,6 +29,8 @@ "@types/react-dom": "^19.2.7", "@vitejs/plugin-react": "^6.1.1", "autoprefixer": "^10.6.1", + "basic-ftp": "^6.2.1", + "dotenv": "^18.0.4", "oxlint": "^1.81.0", "postcss": "^8.5.28", "tailwindcss": "^4.3.3", diff --git a/scripts/deploy-ftp.cjs b/scripts/deploy-ftp.cjs new file mode 100644 index 0000000..62ed43c --- /dev/null +++ b/scripts/deploy-ftp.cjs @@ -0,0 +1,49 @@ +const ftp = require('basic-ftp'); +const path = require('path'); +const dotenv = require('dotenv'); + +dotenv.config(); + +async function deploy() { + const client = new ftp.Client(); + client.ftp.verbose = true; + + const config = { + host: process.env.FTP_HOST || 'ka-el.fr', + user: process.env.FTP_USER || 'antigravity@ka-el.fr', + password: process.env.FTP_PASSWORD || 'dxr1yaor4i', + port: parseInt(process.env.FTP_PORT || '21', 10), + secure: false, // Set to true or 'implicit' if FTPS is enforced + }; + + const localDistDir = path.join(__dirname, '..', 'dist'); + const remoteTargetDir = process.env.FTP_REMOTE_DIR || '/'; + + console.log(`\nšŸš€ [Hostverge FTP Deploy] Connecting to ${config.host} as ${config.user}...`); + + try { + await client.access({ + host: config.host, + user: config.user, + password: config.password, + port: config.port, + secure: config.secure, + }); + + console.log(`āœ… [FTP Connected] Uploading files from "${localDistDir}" to remote "${remoteTargetDir}"...`); + + // Ensure remote directory exists and upload full dist/ content + await client.ensureDir(remoteTargetDir); + await client.clearWorkingDir(); + await client.uploadFromDir(localDistDir); + + console.log(`\nšŸŽ‰ [Success] Application successfully deployed to Hostverge (${config.host}) !\n`); + } catch (err) { + console.error(`\nāŒ [FTP Deploy Failed]:`, err); + process.exit(1); + } finally { + client.close(); + } +} + +deploy();