Parcourir la source

Added and fixed IMAGES_PATH. Webhook deploy script. better readme

rigwild il y a 5 ans
Parent
commit
e459c3886f
4 fichiers modifiés avec 172 ajouts et 29 suppressions
  1. 18 24
      README.md
  2. 2 2
      config.js
  3. 3 3
      docker-compose.yml
  4. 149 0
      webhook_deploy_gogs.js

+ 18 - 24
README.md

@@ -15,39 +15,46 @@ Use the following environment variables to configure the application.
 | ----------- | ------------- | ----------- | :------: | :------: |
 | `PORT` | `5000` | The port used by the started application |  ✅  | ✅ |
 | `SERVE_CLIENT` | `true` | Should the server serve client (Fully local application) |  ✅  | ⬜️ |
+| `IMAGES_PATH` | `./images` | The directory where the images are stored (absolute path if changed ⚠️) |  ✅  | ⬜️ |
+
+Configure more deeply the way the app works by modifying *[config.js](config.js)*.
+
+| Option      | Default value | Description |
+| ----------- | ------------- | ----------- |
+| apiPrefix | `/api` | The url prefix for the API |
+| imageServedUrl | `/api/images` | The url prefix from where the images are served |
+| serverPort | `5000` | The port used by the server |
+| imagesPath | `./images` | The directory where the images are stored |
+| serveClient | `true` | Should the server serve client files from the `/dist` directory |
+| fileNameConvention | `/^(.*)?_([0-9]{2,})\.(.*)$/` | File name convention for images |
+| sceneFileNameBlackList | `['config', 'seuilExpe']` | Files to ignore in scenes |
 
 ### Run server + client
 Linux
 ```sh
-PORT=8080 SERVE_CLIENT=true docker-compose up
+PORT=8080 SERVE_CLIENT=true IMAGE_PATH=/var/images docker-compose up
 ```
 Windows
 ```bat
 SET PORT=8080
 SET SERVE_CLIENT=true
+SET IMAGE_PATH=C:\my\images
 docker-compose up
 ```
 
 ### Run server only
 Linux
 ```sh
-PORT=8080 SERVE_CLIENT=false docker-compose up
+SERVE_CLIENT=false docker-compose up
 ```
 Windows
 ```bat
-SET PORT=8080
 SET SERVE_CLIENT=false
 docker-compose up
 ```
 
 ### Run client only
-Linux
 ```sh
-PORT=8080 docker-compose -f docker-compose.frontapp_only.yml up
-```
-Windows
-```bat
-SET PORT=8080
 docker-compose -f docker-compose.frontapp_only.yml up
 ```
 
@@ -64,7 +71,7 @@ docker-compose -f docker-compose.frontapp_only.yml build
 
 ### Using Windows
 When using Windows, it may happen that you can't properly run the containers because of Windows's path system being different. To circumvant this problem, you can do the [following steps](https://github.com/docker/compose/issues/4303#issuecomment-379563170).
-> 1. On **Command Line**: "_set COMPOSE_CONVERT_WINDOWS_PATHS=1_";
+> 1. On **Command Line**: "set COMPOSE_CONVERT_WINDOWS_PATHS=1";
 > 2. Restart **Docker for Windows**;
 > 3. Go to **Docker for Windows** settings **>** Shared Drives **>** Reset credentials **>** select drive **>** Apply;
 > 4. Reopen **Command Line**;
@@ -87,21 +94,8 @@ export NODE_ENV=production
 Windows
 ```bat
 SET NODE_ENV=production
-SET SERVE_CLIENT=false
 ```
 
-### Configuration 
-Configure the project by modifying *[config.js](config.js)*.
-
-#### Configuration options
-| Option      | Default value | Description |
-| ----------- | ------------- | ----------- |
-| apiPrefix | `/api` | The url prefix for the API |
-| serverPort | `5000` | The port used by the server |
-| imagesPath | `images` | The directory where the images are stored |
-| serveClient | `true` | Should the server serve client files from the `/dist` directory |
-
-
 ### API
 #### Run the server
 ```sh
@@ -133,7 +127,7 @@ yarn run app:dev
 
 
 #### Automatically fix the client code syntax with ESLint
-```
+```sh
 yarn run app:lint
 ```
 

+ 2 - 2
config.js

@@ -14,8 +14,8 @@ export const imageServedUrl = apiPrefix + '/images'
 // The port used by the server
 export const serverPort = parseInt(process.env.PORT, 10) || 5000
 
-// The directory where the images are stored (do not edit it)
-export const imagesPath = path.resolve(__dirname, 'images')
+// The directory where the images are stored
+export const imagesPath = process.env.IMAGES_PATH || path.resolve(__dirname, 'images')
 
 // Should the server serve client files from the `/dist` directory
 export const serveClient = process.env.SERVE_CLIENT === 'true' || true

+ 3 - 3
docker-compose.yml

@@ -11,7 +11,7 @@ services:
           - "${PORT}:${PORT}"
       environment:
           NODE_ENV: production
-          SERVE_CLIENT: $SERVE_CLIENT
-          PORT: $PORT
+          SERVE_CLIENT: "${SERVE_CLIENT:-true}"
+          PORT: "${PORT:-5000}"
       volumes:
-          - ./images:/usr/src/app/images
+          - "${IMAGES_PATH:-./images}:/usr/src/app/images"

+ 149 - 0
webhook_deploy_gogs.js

@@ -0,0 +1,149 @@
+/**
+ * A server that listens on a port for Gogs's webhooks.
+ * It will check for a push event on the master branch, then deploy the project on the machine.
+ * The webhook's secret is check to ensure no malicious request from unknown sources.
+ *
+ * Usage :
+ * Set the "WEBHOOK_SECRET" environment variable with the webhook's secret.
+ *
+ * @see https://gogs.io/docs/features/webhook
+ *
+ *
+ * @author Antoine Sauvage <contact@asauvage.fr>
+ * @license MIT 2019 - https://opensource.org/licenses/MIT
+ * @see https://gist.github.com/rigwild/4238a13cb3501c6e85065b403a71b475
+ */
+
+'use strict'
+
+const fs = require('fs')
+const http = require('http')
+const path = require('path')
+const { promisify } = require('util')
+const exec = promisify(require('child_process').exec)
+
+// The port which this script will listen on
+const port = 12345
+
+// The path to the project directory
+const projectPath = path.resolve('.')
+
+// The webhook secret to check the origin of the webhook event
+// Check the "WEBHOOK_SECRET" environment variable is set
+if (!process.env.WEBHOOK_SECRET && process.env.WEBHOOK_SECRET !== '') {
+  console.error(`${new Date().toLocaleString()} - The "WEBHOOK_SECRET" environment variable is not set.`)
+  process.exit(1)
+}
+const webhookSecret = process.env.WEBHOOK_SECRET
+
+// Check whether the project path exists and script has read access
+console.log(`${new Date().toLocaleString()} - Configured project path : ${projectPath}\n`)
+try {
+  fs.accessSync(projectPath, fs.constants.W_OK)
+  console.log(`${new Date().toLocaleString()} - The project's directory exists and script has write permission.`)
+}
+catch (err) {
+  console.error(`${new Date().toLocaleString()} - The project's directory does not exist or script has not write permission.`, err)
+  process.exit(1)
+}
+
+
+// Check the "PORT" environment variable is set to a valid integer
+if (!process.env.PORT || !parseInt(process.env.PORT, 10)) {
+  console.error(`${new Date().toLocaleString()} - The "PORT" environment variable is not set or is not an integer.`)
+  process.exit(1)
+}
+
+// Check the "SERVE_CLIENT" environment variable is set to 'true' or 'false'
+if (!process.env.SERVE_CLIENT || !['true', 'false'].some(x => x === process.env.SERVE_CLIENT)) {
+  console.error(`${new Date().toLocaleString()} - The "SERVE_CLIENT" environment variable is not set or is not 'true' or 'false'`)
+  process.exit(1)
+}
+
+const env = {
+  PORT: parseInt(process.env.PORT, 10),
+  SERVE_CLIENT: process.env.SERVE_CLIENT,
+  IMAGES_PATH: process.env.IMAGES_PATH
+}
+// Recap used environment variables
+Object.keys(env).forEach(x => console.log(`${x}=${env[x]}`))
+
+// The script that will be executed by the machine
+const deployScript = `cd ${projectPath}` +
+  ' && git reset --hard HEAD' +
+  ' && git pull origin master' +
+  ' && docker-compose down' +
+  ' && docker-compose build' +
+  ' && docker-compose up -d'
+
+console.log('\nConfiguration is valid. Starting the webhook-listener server ...')
+
+const deploy = async () => {
+  try {
+    console.log(`${new Date().toLocaleString()} - Deploying project ...`)
+    const startTime = process.hrtime()
+    const { stdout, stderr } = await exec(
+      deployScript,
+      {
+        cwd: projectPath,
+        env
+      }
+    )
+    const endTime = process.hrtime(startTime)
+
+    // Logs received from the deploy script are sent in stdout :
+    // git fetch and docker-compose build/up are writing their success logs in stderr...
+    // A deploy fail will be printed in stderr (in the catch)
+    console.log('stdout :\n', stdout)
+    console.log('stderr :\n', stderr)
+    console.log(`\n${new Date().toLocaleString()} - Project successfully deployed with Docker.`)
+    console.log(`Total deploy time : ${endTime[0]}s and ${endTime[1] / 1000000}ms.`)
+  }
+  catch (err) {
+    console.error(`\n${new Date().toLocaleString()} - Error deploying project.\n`, err)
+  }
+}
+
+// Configuration is fine, start the server
+http.createServer((req, res) => {
+  // Check the method is POST
+  if (req.method !== 'POST') {
+    res.statusCode = 400
+    res.write('Wrong HTTP method.')
+    res.end()
+    return
+  }
+
+  // Check the event is a push
+  if (req.headers['x-gogs-event'] !== 'push') {
+    res.statusCode = 200
+    res.write('OK. Not a push event.')
+    res.end()
+    return
+  }
+
+  // Answer OK and close the connection
+  res.statusCode = 200
+  res.write('OK')
+  res.end()
+
+  let body = []
+  req.on('data', chunk => body.push(chunk))
+  req.on('end', () => {
+    try {
+      body = JSON.parse(Buffer.concat(body).toString())
+      // Check if the event was on master
+      if (!body.ref || body.ref !== 'refs/heads/master') return
+
+      // Check if secret matches
+      if (!body.secret || body.secret !== webhookSecret) return
+
+      console.log(`${new Date()} - Valid webhook event. Push on master was sent. Deployement process starts.`)
+      deploy()
+    }
+    catch (err) {
+      console.error(`${new Date()} - Invalid JSON was received`)
+    }
+  })
+}).listen(port)
+console.log(`${new Date().toLocaleString()} - Server is listening on http://localhost:${port}/`)