ci: add CI/CD FTP deployment workflows and local deploy script for Hostverge

This commit is contained in:
streaper2
2026-09-27 18:25:19 +02:00
parent 88f23caf3b
commit 3af47720d3
7 changed files with 235 additions and 0 deletions

View File

@@ -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

View File

@@ -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

41
.github/workflows/deploy.yml vendored Normal file
View File

@@ -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

34
.gitlab-ci.yml Normal file
View File

@@ -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

28
package-lock.json generated
View File

@@ -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",

View File

@@ -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",

49
scripts/deploy-ftp.cjs Normal file
View File

@@ -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();