From 1d978c18d1c8cb86e302a7223b4f7610a492f323 Mon Sep 17 00:00:00 2001 From: lowlighter <22963968+lowlighter@users.noreply.github.com> Date: Thu, 7 Jul 2022 00:30:41 -0400 Subject: [PATCH] feat(app/web): add endpoint to stop instance --- .github/workflows/ci.yml | 21 ++++++++++----------- source/app/web/instance.mjs | 18 ++++++++++++++++++ source/app/web/settings.example.json | 3 +++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e52109b..365266c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -217,11 +217,20 @@ jobs: use_mocked_data: yes verify: yes + # Deploy to metrics.lecoq.io + deploy-latest: + name: Deploy lowlighter/metrics@latest + runs-on: ubuntu-latest + needs: [ update-latest ] + steps: + - name: Deploy web instance + run: "curl -X POST -H 'Authorization: ${{ secrets.WEB_DEPLOY_TOKEN }}' https://metrics.lecoq.io/.control/stop" + # Publish GitHub release publish-release: name: Publish release runs-on: ubuntu-latest - needs: [ action-latest-test ] + needs: [ action-latest-test, deploy-latest ] steps: - name: Checkout repository uses: actions/checkout@v2 @@ -237,13 +246,3 @@ jobs: GITHUB_TOKEN: ${{ github.token }} GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_COMMIT_MESSAGE: ${{ github.event.head_commit.message }} - - # Deploy to metrics.lecoq.io - deploy-latest: - name: Deploy lowlighter/metrics@latest - runs-on: ubuntu-latest - needs: [ action-latest-test ] - if: contains(github.event.head_commit.message, '[deploy]') - steps: - - name: Deploy web instance - run: "curl -H 'Content-Type: application/json' --data '${{ secrets.WEB_DEPLOY_TOKEN }}' -X POST https://deploy.metrics.lecoq.io" diff --git a/source/app/web/instance.mjs b/source/app/web/instance.mjs index 83147ea4..537a121e 100644 --- a/source/app/web/instance.mjs +++ b/source/app/web/instance.mjs @@ -399,6 +399,24 @@ export default async function({sandbox = false} = {}) { app.get("/embed/*", (req, res) => res.status(405).send("Method not allowed: this endpoint is not available")) } + //Control endpoints + if ((conf.settings.control?.token)&&(conf.settings.control.token)) { + const middleware = (req, res, next) => { + console.log(`metrics/app/control > ${req.method} > ${req.url}`) + if (req.headers.authorization === conf.settings.control.token) { + next() + return + } + return res.status(401).send("Unauthorized: invalid token") + } + app.post("/.control/stop", limiter, middleware, async (req, res) => { + console.debug("metrics/app/control > instance will be stopped in a few seconds") + res.status(202).send("Accepted: instance will be stopped in a few seconds") + await new Promise(resolve => setTimeout(resolve, 5000)) + process.exit(1) + }) + } + //Listen app.listen(port, () => console.log([ diff --git a/source/app/web/settings.example.json b/source/app/web/settings.example.json index 3ac35afb..02d93fc4 100644 --- a/source/app/web/settings.example.json +++ b/source/app/web/settings.example.json @@ -20,6 +20,9 @@ "by": "", "//": "Web instance host (displayed in footer)", "link": "", "//": "Web instance host link (displayed in footer)" }, + "control":{ + "token": null, "//": "Control token (can be used by external services to perform actions on instance, such as stopping it for redeploys)" + }, "community": { "templates": [], "//": "Additional community templates to setup" },