{"id":20428311,"url":"https://github.com/tomasbjerre/serverless-server-spawner","last_synced_at":"2026-05-10T18:02:22.304Z","repository":{"id":143399970,"uuid":"437622104","full_name":"tomasbjerre/serverless-server-spawner","owner":"tomasbjerre","description":"Minimal serverless implementation that only requires NodeJS.","archived":false,"fork":false,"pushed_at":"2022-02-06T06:57:35.000Z","size":5347,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-16T13:06:18.862Z","etag":null,"topics":["serverless"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomasbjerre.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-12T18:17:03.000Z","updated_at":"2021-12-20T10:45:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"f4a5a724-4f36-404d-bc4b-9feb92486114","html_url":"https://github.com/tomasbjerre/serverless-server-spawner","commit_stats":null,"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomasbjerre%2Fserverless-server-spawner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomasbjerre%2Fserverless-server-spawner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomasbjerre%2Fserverless-server-spawner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomasbjerre%2Fserverless-server-spawner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomasbjerre","download_url":"https://codeload.github.com/tomasbjerre/serverless-server-spawner/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241969761,"owners_count":20050570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["serverless"],"created_at":"2024-11-15T07:25:09.414Z","updated_at":"2026-05-10T18:02:17.242Z","avatar_url":"https://github.com/tomasbjerre.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Serverless Server Spawner\n\n[![NPM](https://img.shields.io/npm/v/serverless-server-spawner.svg?style=flat-square)](https://www.npmjs.com/package/serverless-server-spawner)\n\n![Demo](demo.gif)\n\nBasic idea:\n\n- Start it with `npx serverless-server-spawner`.\n- Invoke it with `https://localhost:P/?cloneurl=C\u0026branch=B`\n  - `P` - A configurable port.\n  - `C` - A clone URL of a git Repo.\n  - `B` - A branch in repo `C`.\n- It will\n  - Clone that repo.\n  - Checkout that branch.\n  - Recognize what was cloned.\n  - Find a free port\n  - Spawn a server\n  - Wait for the spawned server to start\n  - Redirect to the spawned server\n  - Keep that server alive for configurable amount of time\n\nRepositories are recognized using configurable matchers. A matcher:\n\n- Determines a fitting name\n- How to prepare the repository before start\n- How to start the server\n\nAs the servers are spawned it will keep track of all processes. Provides an API as well as a dashboard showing status of the setup.\n\n![A simple flow](/flow.png)\n\n## Use cases\n\n- Can be used to test feature-branches. Adding links from pull-requests to this server and let this server spawn servers running those features.\n- ...\n\nSee example in this sandbox:\nhttps://github.com/tomasbjerre/serverless-sandbox\n\n## Matchers\n\n- Put them in a folder\n- name them like `*.matcher.js`\n\nExample: `serverless-matchers/example.matcher.js`\n\nContent should be like:\n\n```js\nfunction isMatching(repoFolder) {\n  try {\n    return require(`${repoFolder}/package.json`).scripts['start'] != undefined;\n  } catch {\n    return false;\n  }\n}\n\nfunction getName(repoFolder) {\n  return require(`${repoFolder}/package.json`).name;\n}\n\nfunction getPrepareCommand(repoFolder) {\n  return `npm install`;\n}\n\nfunction preStart(repoFolder, env) {\n  // Do struff before start\n  // env contains port in evn.PORT\n}\n\nfunction getStartCommand(repoFolder) {\n  // Environment variable named \"PORT\" contains the allocated port\n  return `npm run start`;\n}\n\nfunction isReady(runLogContent, serverPort) {\n  // Optionally check log to see if server ready.\n  //return true;\n\n  //return new RegExp(`https?://(127.0.0.1|localhost):${serverPort}`,'g')\n  //  .test(runLogContent)\n\n  return new RegExp(`${serverPort}`, 'g').test(runLogContent);\n}\n\nmodule.exports = {\n  isMatching,\n  getName,\n  getPrepareCommand,\n  preStart,\n  getStartCommand,\n  isReady,\n};\n```\n\nAnd you point at them with:\n\n```sh\nnpx serverless-server-spawner \\\n  --matchers-folder /path/to/serverless-matchers\n```\n\n## Command line arguments\n\n\u003c!-- Commander help //--\u003e\n\n```shell\nUsage:  serverless-server-spawner [options]\n\nOptions:\n  -ws, --workspace \u003cfolder\u003e                            Filesystem to work with.\n  -mf, --matchers-folder \u003cfolder\u003e                      Folder containing matchers.\n  -p, --port \u003cnumber\u003e                                  Server port to use (default: \"8080\")\n  -d, --dashboard-url \u003curl\u003e                            Base URL of dashboard (default: \"http://localhost:8080\")\n  -ttl, --time-to-live \u003cminutes\u003e                       Time to keep server running after it was started. (default: \"30\")\n  -bbsat, --bitbucket-server-access-token \u003ctoken\u003e      Bitbucket Server access token\n  -bbsu, --bitbucket-server-url \u003curl\u003e                  Bitbucket Server to use for REST integration (https://bbs/rest/api/latest)\n  -bbsp, --bitbucket-server-projects \u003cprojects\u003e        Bitbucket Server projects. Empty will include all projects.\n  -mip, --minimum-port-number \u003cport\u003e                   Minimum port number to use for spawned servers (default: \"9000\")\n  -map, --maximum-port-number \u003cport\u003e                   Maximum port number to use for spawned servers (default: \"9999\")\n  -ict, --integration-cache-ttl \u003cminutes\u003e              Cache time to live, seconds (default: \"120\")\n  -nc, --no-cleanup                                    Do not cleanup state on startup: kill servers and clean workspace\n  -msbd, --minimum-seconds-between-dispatch \u003cseconds\u003e  Minimum time between spawning new servers from same url and branch (default: \"10\")\n  -h, --help                                           display help for command\n```\n\n## API\n\nRESTful API of the this server.\n\nThe main entry point for new repo/branches is `dispatch`. It will start a server and, when started, redirect user to it.\n\n```\nGET /api/dispatch?cloneurl={cloneUrl}\u0026branch={branch}\n```\n\n```\nGET /api/servers\n```\n\n```\nGET /api/servers/:id\n```\n\n```\nGET /api/servers/:id/state\n```\n\nStop, and cleanup, the server.\n\n```\nPOST /api/servers/:id/stop\n```\n\n```\nGET /api/servers/:id/log/spawn\n```\n\n```\nGET /api/servers/:id/log/clone\n```\n\n```\nGET /api/servers/:id/log/prepare\n```\n\n```\nGET /api/servers/:id/log/run\n```\n\nIf a Git service was configured, this will respond with clone URL:s in that service.\n\n```\nGET /api/cloneurlcategories\n```\n\nIf a Git service was configured, this will respond with branches in categories.\n\n```\nGET /api/cloneurlcategories/:category1/:category2/branches\n```\n\nClear all caches.\n\n```\nPOST /api/clearcache\n```\n\nGet settings used, like port range. So that you can calculate available ports.\n\n```\nGET /api/settings\n```\n\n## Developer instructions\n\nDuring development it might help to start it with:\n\n```shell\nnpm install \\\n \u0026\u0026 npm run build \\\n \u0026\u0026 node ./lib/spawner/bin.js \\\n --matchers-folder /home/bjerre/workspace/serverless/serverless-sandbox/matchers \\\n --time-to-live 1\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomasbjerre%2Fserverless-server-spawner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomasbjerre%2Fserverless-server-spawner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomasbjerre%2Fserverless-server-spawner/lists"}