revive deploy
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# .github/workflows/deploy.yml
|
||||
name: Deploy openDAW studio
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry:
|
||||
description: "Dry run (no upload)"
|
||||
required: false
|
||||
default: 'true'
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Checkout main repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: ⬇️ Checkout private submodule
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: andremichelle/opendaw-lib
|
||||
path: lib
|
||||
ssh-key: ${{ secrets.SUBMODULE_SSH_KEY }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: 🦄 Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: 📦 Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: 🏗️ Build project
|
||||
shell: bash
|
||||
run: |
|
||||
bash ./rebuild.sh
|
||||
|
||||
- name: 🚚 Run deploy script
|
||||
env:
|
||||
TERM: xterm-256color
|
||||
SFTP_HOST: ${{ secrets.SFTP_HOST }}
|
||||
SFTP_PORT: ${{ secrets.SFTP_PORT }}
|
||||
SFTP_USERNAME: ${{ secrets.SFTP_USERNAME }}
|
||||
SFTP_PASSWORD: ${{ secrets.SFTP_PASSWORD }}
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
DRY_RUN: ${{ inputs.dry && '1' || '0' }}
|
||||
run: |
|
||||
npx ts-node --transpile-only deploy/run.ts ${{ inputs.dry && '--dry' || '' }}
|
||||
@@ -0,0 +1,17 @@
|
||||
name: Notify Discord
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
- run: npm ci
|
||||
- run: npx ts-node --transpile-only deploy/discord.ts
|
||||
@@ -0,0 +1,18 @@
|
||||
(async () => {
|
||||
const webhookUrl = process.env.DISCORD_WEBHOOK
|
||||
if (!webhookUrl) {
|
||||
console.error("Missing DISCORD_WEBHOOK")
|
||||
process.exit(1)
|
||||
}
|
||||
const content = "🧪 Discord test from GitHub Actions"
|
||||
const res = await fetch(webhookUrl, {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({content})
|
||||
})
|
||||
if (!res.ok) {
|
||||
console.error(`Failed to post: ${res.status}`, await res.text())
|
||||
process.exit(1)
|
||||
}
|
||||
console.log("✅ Discord message sent")
|
||||
})()
|
||||
@@ -0,0 +1,85 @@
|
||||
import SftpClient from "ssh2-sftp-client"
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
|
||||
const config = {
|
||||
host: process.env.SFTP_HOST,
|
||||
port: Number(process.env.SFTP_PORT),
|
||||
username: process.env.SFTP_USERNAME,
|
||||
password: process.env.SFTP_PASSWORD
|
||||
} as const
|
||||
|
||||
const DRY_RUN = process.env.DRY_RUN === "1" || process.argv.includes("--dry")
|
||||
console.info(`DRY_RUN: ${DRY_RUN}`)
|
||||
const env = Object.entries({
|
||||
SFTP_HOST: process.env.SFTP_HOST,
|
||||
SFTP_PORT: process.env.SFTP_PORT,
|
||||
SFTP_USERNAME: process.env.SFTP_USERNAME,
|
||||
SFTP_PASSWORD: process.env.SFTP_PASSWORD,
|
||||
DISCORD_WEBHOOK: process.env.DISCORD_WEBHOOK
|
||||
})
|
||||
const missing = env.filter(([, v]) => !v).map(([k]) => k)
|
||||
if (missing.length > 0) {
|
||||
throw new Error(`Missing secrets/vars: ${missing.join(", ")}`)
|
||||
}
|
||||
if (DRY_RUN) {
|
||||
console.log("✅ All secrets & variables are set. Nothing was uploaded (dry-run).")
|
||||
process.exit(0)
|
||||
}
|
||||
const sftp = new SftpClient()
|
||||
const staticFolders = ["/viscious-speed"]
|
||||
|
||||
async function deleteDirectory(remoteDir: string) {
|
||||
const items = await sftp.list(remoteDir)
|
||||
for (const item of items) {
|
||||
const remotePath = path.posix.join(remoteDir, item.name)
|
||||
if (staticFolders.includes(remotePath)) continue
|
||||
if (item.type === "d") {
|
||||
await deleteDirectory(remotePath)
|
||||
await sftp.rmdir(remotePath, true)
|
||||
} else {
|
||||
await sftp.delete(remotePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadDirectory(localDir: string, remoteDir: string) {
|
||||
for (const file of fs.readdirSync(localDir)) {
|
||||
const localPath = path.join(localDir, file)
|
||||
const remotePath = path.posix.join(remoteDir, file)
|
||||
if (fs.lstatSync(localPath).isDirectory()) {
|
||||
await sftp.mkdir(remotePath, true).catch(() => {/* exists */})
|
||||
if (staticFolders.includes(remotePath)) continue
|
||||
await uploadDirectory(localPath, remotePath)
|
||||
} else {
|
||||
console.log(`upload ${remotePath}`)
|
||||
await sftp.put(localPath, remotePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------- main -------------------------------------------------
|
||||
(async () => {
|
||||
console.log(`⏩ upload…`)
|
||||
await sftp.connect(config)
|
||||
await deleteDirectory("/")
|
||||
await uploadDirectory("./packages/app/studio/dist", "/")
|
||||
await sftp.end()
|
||||
const webhookUrl = process.env.DISCORD_WEBHOOK
|
||||
if (webhookUrl) {
|
||||
console.log("posting to discord...")
|
||||
const now = Math.floor(Date.now() / 1000) // in seconds
|
||||
const content = `🚀 **openDAW** has been deployed to <https://opendaw.studio> <t:${now}:R>.`
|
||||
try {
|
||||
const response = await fetch(webhookUrl, {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({content})
|
||||
})
|
||||
console.log(response)
|
||||
} catch (error) {
|
||||
console.warn(error)
|
||||
}
|
||||
}
|
||||
console.log("deploy complete")
|
||||
})()
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2016",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"files": [
|
||||
"run.ts"
|
||||
]
|
||||
}
|
||||
Generated
+135
@@ -12,12 +12,14 @@
|
||||
"packages/**/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/ssh2-sftp-client": "^9.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
||||
"@typescript-eslint/parser": "^7.1.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"lerna": "^8.2.3",
|
||||
"prettier": "^3.6.2",
|
||||
"ssh2-sftp-client": "^12.0.1",
|
||||
"turbo": "^2.5.5",
|
||||
"typescript": "^5.9.2",
|
||||
"vitest": "^3.1.3"
|
||||
@@ -2797,6 +2799,43 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/ssh2": {
|
||||
"version": "1.15.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.5.tgz",
|
||||
"integrity": "sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "^18.11.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ssh2-sftp-client": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/ssh2-sftp-client/-/ssh2-sftp-client-9.0.5.tgz",
|
||||
"integrity": "sha512-cpUO6okDusnfLw2hnmaBiomlSchIWNVcCdpywLRsg/h9Q1TTiUSrzhkn5sJeeyTM8h6xRbZEZZjgWtUXFDogHg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/ssh2": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ssh2/node_modules/@types/node": {
|
||||
"version": "18.19.121",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.121.tgz",
|
||||
"integrity": "sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ssh2/node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/wicg-file-system-access": {
|
||||
"version": "2023.10.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/wicg-file-system-access/-/wicg-file-system-access-2023.10.6.tgz",
|
||||
@@ -3379,6 +3418,16 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/assertion-error": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
|
||||
@@ -3442,6 +3491,16 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||
@@ -3530,6 +3589,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/buildcheck": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz",
|
||||
"integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/byte-size": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/byte-size/-/byte-size-8.1.1.tgz",
|
||||
@@ -4142,6 +4211,21 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cpu-features": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz",
|
||||
"integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"buildcheck": "~0.0.6",
|
||||
"nan": "^2.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@@ -7841,6 +7925,14 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.23.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz",
|
||||
"integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
@@ -9926,6 +10018,42 @@
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/ssh2": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.16.0.tgz",
|
||||
"integrity": "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"asn1": "^0.2.6",
|
||||
"bcrypt-pbkdf": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.16.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"cpu-features": "~0.0.10",
|
||||
"nan": "^2.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ssh2-sftp-client": {
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ssh2-sftp-client/-/ssh2-sftp-client-12.0.1.tgz",
|
||||
"integrity": "sha512-ICJ1L2PmBel2Q2ctbyxzTFZCPKSHYYD6s2TFZv7NXmZDrDNGk8lHBb/SK2WgXLMXNANH78qoumeJzxlWZqSqWg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"concat-stream": "^2.0.0",
|
||||
"ssh2": "^1.16.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.20.4"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://square.link/u/4g7sPflL"
|
||||
}
|
||||
},
|
||||
"node_modules/ssri": {
|
||||
"version": "10.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz",
|
||||
@@ -10631,6 +10759,13 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
|
||||
"dev": true,
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
"publish-sdk": "lerna publish"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ssh2-sftp-client": "^9.0.5",
|
||||
"ssh2-sftp-client": "^12.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
||||
"@typescript-eslint/parser": "^7.1.0",
|
||||
"eslint": "^8.57.0",
|
||||
|
||||
Reference in New Issue
Block a user