@faable/faable 1.4.12 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/commands/deploy/check_environment.js +1 -0
  2. package/dist/commands/deploy/deploy_command.js +22 -32
  3. package/dist/commands/deploy/index.js +0 -5
  4. package/dist/commands/deploy/node-pipeline/analyze_package.js +34 -0
  5. package/dist/commands/deploy/node-pipeline/build_project.js +25 -0
  6. package/dist/{builder/node/prepare_dockerfile.js → commands/deploy/node-pipeline/bundle_docker.js} +12 -7
  7. package/dist/commands/deploy/node-pipeline/index.js +25 -0
  8. package/dist/commands/deploy/runtime-detect/runtime_detection.js +1 -2
  9. package/dist/commands/deploy/runtime-detect/strategies/docker.js +3 -1
  10. package/dist/commands/deploy/runtime-detect/strategies/nodejs.js +20 -2
  11. package/dist/index.js +11 -0
  12. package/dist/lib/Configuration.js +9 -8
  13. package/dist/log.js +9 -7
  14. package/package.json +2 -2
  15. package/dist/builder/docker/index.js +0 -10
  16. package/dist/builder/index.js +0 -17
  17. package/dist/builder/node/analyze_package.js +0 -25
  18. package/dist/builder/node/build_project.js +0 -27
  19. package/dist/builder/node/engine_version.js +0 -31
  20. package/dist/builder/node/index.js +0 -26
  21. package/dist/builder/python/index.js +0 -17
  22. package/dist/builder/python/prepare_dockerfile.js +0 -40
  23. package/dist/builder/python/templates/Dockerfile +0 -26
  24. package/dist/builder/python/templates/entrypoint.sh +0 -7
  25. package/dist/commands/deploy/runtime-detect/strategies/python.js +0 -19
  26. /package/dist/{builder/node → commands/deploy/node-pipeline}/templates/Dockerfile +0 -0
  27. /package/dist/{builder/node → commands/deploy/node-pipeline}/templates/entrypoint.sh +0 -0
@@ -5,6 +5,7 @@ const check_environment = async () => {
5
5
  await cmd("docker ps");
6
6
  }
7
7
  catch (error) {
8
+ console.log(error);
8
9
  throw new Error(`Docker is not running`);
9
10
  }
10
11
  };
@@ -2,19 +2,13 @@ import { log } from '../../log.js';
2
2
  import { upload_tag } from './upload_tag.js';
3
3
  import { check_environment } from './check_environment.js';
4
4
  import { context } from '../../api/context.js';
5
+ import { build_node } from './node-pipeline/index.js';
5
6
  import { runtime_detection } from './runtime-detect/runtime_detection.js';
6
- import { import_builder } from '../../builder/index.js';
7
- import { Configuration } from '../../lib/Configuration.js';
8
7
  import { cmd } from '../../lib/cmd.js';
9
8
 
10
9
  const deploy_command = async (args) => {
11
10
  const workdir = args.workdir || process.cwd();
12
- const flags = {
13
- upload: args.onlybuild ? false : true,
14
- };
15
11
  const { api } = await context();
16
- // Check if we can build docker images
17
- await check_environment();
18
12
  // Resolve runtime
19
13
  const { app_name, runtime } = await runtime_detection(workdir);
20
14
  const name = args.app_slug || app_name;
@@ -23,35 +17,31 @@ const deploy_command = async (args) => {
23
17
  }
24
18
  // Get app from Faable API
25
19
  const app = await api.getBySlug(name);
26
- log.info(`🚀 Deploying ${app.name} (${app.id}) runtime=${runtime}`);
27
- // Select builder
28
- let builder = await import_builder(runtime);
29
- const ctx = {
30
- app,
31
- workdir,
32
- log: log.child({ runtime }),
33
- config: Configuration.instance(workdir),
34
- };
35
- // Do build
36
- const { dockerfile, params } = await builder(ctx);
37
- // Compile docker image
38
- log.info(`📦 Packaging...`);
39
- const timeout = 10 * 60 * 1000; // 10 minute timeout
40
- await cmd(`docker build -t ${app.id} ${workdir} -f -<<EOF\n${dockerfile}\nEOF`, { timeout, enableOutput: true });
41
- // Upload to Faable registry
42
- if (flags.upload) {
43
- const { upload_tagname } = await upload_tag({ app, api });
44
- // Create a deployment for this image
45
- await api.createDeployment({
46
- app_id: app.id,
47
- image: upload_tagname,
48
- ...(params || {}),
20
+ // Check if we can build docker images
21
+ await check_environment();
22
+ log.info(`🚀 Deploying ${app.name} (${app.id}) runtime=${runtime.name}-${runtime.version} `);
23
+ let type;
24
+ if (runtime.name == "node") {
25
+ const node_result = await build_node(app, {
26
+ workdir,
27
+ runtime,
28
+ });
29
+ type = node_result.type;
30
+ }
31
+ else if (runtime.name == "docker") {
32
+ type = "node";
33
+ await cmd(`docker build -t ${app.id} .`, {
34
+ enableOutput: true,
49
35
  });
50
- log.info(`🌍 Deployment created -> https://${app.url}`);
51
36
  }
52
37
  else {
53
- log.info(`❌ Upload canceled, remove --onlybuild otherwise`);
38
+ throw new Error(`No build pipeline for runtime=${runtime.name}`);
54
39
  }
40
+ // Upload to Faable registry
41
+ const { upload_tagname } = await upload_tag({ app, api });
42
+ // Create a deployment for this image
43
+ await api.createDeployment({ app_id: app.id, image: upload_tagname, type });
44
+ log.info(`🌍 Deployment created -> https://${app.url}`);
55
45
  };
56
46
 
57
47
  export { deploy_command };
@@ -13,11 +13,6 @@ const deploy = {
13
13
  alias: "w",
14
14
  type: "string",
15
15
  description: "Working directory",
16
- })
17
- .option("onlybuild", {
18
- type: "boolean",
19
- default: false,
20
- description: "Just build",
21
16
  })
22
17
  .showHelpOnFail(false);
23
18
  },
@@ -0,0 +1,34 @@
1
+ import fs from 'fs-extra';
2
+ import path__default from 'path';
3
+ import { log } from '../../../log.js';
4
+ import * as R from 'ramda';
5
+
6
+ const analyze_package = async (params) => {
7
+ const workdir = params.workdir;
8
+ const package_file = path__default.join(path__default.resolve(workdir), "package.json");
9
+ log.info(`Loading config from package.json`);
10
+ const pkg = await fs.readJSON(package_file);
11
+ // Check if build is required to run
12
+ const build_script = process.env.FAABLE_NPM_BUILD_SCRIPT
13
+ ? process.env.FAABLE_NPM_BUILD_SCRIPT
14
+ : pkg?.scripts["build"]
15
+ ? "build"
16
+ : null;
17
+ if (!build_script) {
18
+ log.info(`No build script on package.json`);
19
+ }
20
+ let type = "node";
21
+ // Detect nextjs deployment type
22
+ const next_dep = R.lensPath(["dependencies", "next"]);
23
+ const next_devdep = R.lensPath(["devDependencies", "next"]);
24
+ if (R.view(next_dep, pkg) || R.view(next_devdep, pkg)) {
25
+ type = "next";
26
+ }
27
+ log.info(`⚡️ Detected deployment type=${type}`);
28
+ return {
29
+ build_script,
30
+ type,
31
+ };
32
+ };
33
+
34
+ export { analyze_package };
@@ -0,0 +1,25 @@
1
+ import { log } from '../../../log.js';
2
+ import { cmd } from '../../../lib/cmd.js';
3
+ import { Configuration } from '../../../lib/Configuration.js';
4
+
5
+ const build_project = async (args) => {
6
+ const build_script = args.build_script;
7
+ const build_command = build_script
8
+ ? `yarn run ${build_script}`
9
+ : Configuration.instance().buildCommand;
10
+ if (build_command) {
11
+ const cwd = args.cwd || process.cwd();
12
+ log.info(`⚙️ Building project [${build_command}]...`);
13
+ const timeout = 1000 * 60 * 100; // 100 minute timeout
14
+ await cmd(build_command, {
15
+ timeout,
16
+ cwd,
17
+ enableOutput: true,
18
+ });
19
+ }
20
+ else {
21
+ log.info(`⚡️ No build step`);
22
+ }
23
+ };
24
+
25
+ export { build_project };
@@ -1,7 +1,10 @@
1
+ import { log } from '../../../log.js';
2
+ import { cmd } from '../../../lib/cmd.js';
1
3
  import fs from 'fs-extra';
2
4
  import Handlebars from 'handlebars';
3
5
  import * as path from 'path';
4
6
  import { fileURLToPath } from 'url';
7
+ import { Configuration } from '../../../lib/Configuration.js';
5
8
 
6
9
  const __filename = fileURLToPath(import.meta.url);
7
10
  const __dirname = path.dirname(__filename);
@@ -21,18 +24,20 @@ Handlebars.registerHelper("escape", function (variable) {
21
24
  // Docker template file
22
25
  const docker_template = Handlebars.compile(dockerfile);
23
26
  const entrypoint_template = Handlebars.compile(entrypoint);
24
- const prepare_dockerfile = async (ctx, params) => {
25
- const { app, workdir, log, config } = ctx;
26
- const { template_context } = params;
27
+ const bundle_docker = async (props) => {
28
+ const { app, workdir, template_context } = props;
27
29
  const entrypoint_custom = entrypoint_template(template_context);
28
- const start_command = config.getConfigProperty("startCommand", "npm run start");
29
- log.info(`✅ Start command set to "${start_command}"`);
30
+ const start_command = Configuration.instance().startCommand;
31
+ log.info(`⚙️ Start command: ${start_command}`);
30
32
  const dockerfile = docker_template({
31
33
  from: template_context.from,
32
34
  entry_script: entrypoint_custom,
33
35
  start_command,
34
36
  });
35
- return { dockerfile };
37
+ log.info(`📦 Packaging inside a docker image`);
38
+ // Build options
39
+ const timeout = 10 * 60 * 1000; // 10 minute timeout
40
+ await cmd(`docker build -t ${app.id} ${workdir} -f -<<EOF\n${dockerfile}\nEOF`, { timeout, enableOutput: true });
36
41
  };
37
42
 
38
- export { prepare_dockerfile };
43
+ export { bundle_docker };
@@ -0,0 +1,25 @@
1
+ import { bundle_docker } from './bundle_docker.js';
2
+ import { analyze_package } from './analyze_package.js';
3
+ import { build_project } from './build_project.js';
4
+
5
+ const build_node = async (app, options) => {
6
+ // log.info(`🚀 Build Toolchain ${app.name} [${app.id}]`);
7
+ const { workdir, runtime } = options;
8
+ if (!runtime.version) {
9
+ throw new Error("Runtime version not specified for node");
10
+ }
11
+ // Analyze package.json to check if build is needed
12
+ const { build_script, type } = await analyze_package({ workdir });
13
+ await build_project({ app, build_script });
14
+ // Bundle project inside a docker image
15
+ await bundle_docker({
16
+ app,
17
+ workdir,
18
+ template_context: {
19
+ from: `node:${runtime.version}`,
20
+ },
21
+ });
22
+ return { type };
23
+ };
24
+
25
+ export { build_node };
@@ -1,14 +1,13 @@
1
1
  import { strategy_nodejs } from './strategies/nodejs.js';
2
2
  import * as R from 'ramda';
3
3
  import { has_any_of_files } from './helpers/has_any_of_files.js';
4
- import { strategy_python } from './strategies/python.js';
5
4
  import { strategy_docker } from './strategies/docker.js';
6
5
 
7
6
  const runtime_detection = async (workdir) => {
8
7
  const has = R.curry(has_any_of_files);
9
8
  const strategy = R.cond([
10
9
  [has(["package.json"]), R.always(strategy_nodejs)],
11
- [has(["requirements.txt"]), R.always(strategy_python)],
10
+ // [has(["requirements.txt"]), R.always(strategy_python)],
12
11
  [has(["Dockerfile"]), R.always(strategy_docker)],
13
12
  ])(workdir);
14
13
  if (!strategy) {
@@ -1,6 +1,8 @@
1
1
  const strategy_docker = async (workdir) => {
2
2
  return {
3
- runtime: "docker",
3
+ runtime: {
4
+ name: "docker",
5
+ },
4
6
  };
5
7
  };
6
8
 
@@ -1,5 +1,7 @@
1
1
  import fs from 'fs-extra';
2
2
  import path__default from 'path';
3
+ import { cmd } from '../../../../lib/cmd.js';
4
+ import { log } from '../../../../log.js';
3
5
 
4
6
  /**
5
7
  * Strategy to detect app name from package.json
@@ -10,13 +12,29 @@ import path__default from 'path';
10
12
  const strategy_nodejs = async (workdir) => {
11
13
  const packageJSONFile = path__default.join(workdir, "package.json");
12
14
  // Check we have a valid name
13
- const { name } = fs.readJSONSync(packageJSONFile);
15
+ const { name, engines } = fs.readJSONSync(packageJSONFile);
14
16
  if (!name) {
15
17
  throw new Error("Missing name in package.json");
16
18
  }
19
+ // Use engines.node if found
20
+ let runtime_version = "18.19.0";
21
+ if (engines?.node) {
22
+ try {
23
+ const check_cmd = `npm view node@"${engines.node}" version | tail -n 1 | cut -d "'" -f2`;
24
+ const out = await cmd(check_cmd);
25
+ runtime_version = out.stdout.toString();
26
+ log.info(`Using node@${runtime_version} from engines in package.json (${engines.node})`);
27
+ }
28
+ catch (e) {
29
+ throw new Error(`Node version is not valid (${engines.node})`);
30
+ }
31
+ }
17
32
  return {
18
33
  app_name: name,
19
- runtime: "node",
34
+ runtime: {
35
+ name: "node",
36
+ version: runtime_version,
37
+ },
20
38
  };
21
39
  };
22
40
 
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ import { deploy } from './commands/deploy/index.js';
6
6
  import { log } from './log.js';
7
7
  import { init } from './commands/init/index.js';
8
8
  import { version } from './config.js';
9
+ import { Configuration } from './lib/Configuration.js';
9
10
 
10
11
  const yg = yargs();
11
12
  yg.scriptName("faable")
@@ -17,6 +18,16 @@ yg.scriptName("faable")
17
18
  description: "Path to the local `faable.json` file",
18
19
  string: true,
19
20
  })
21
+ .middleware(function (argv) {
22
+ if (argv.config) {
23
+ Configuration.instance().setConfigFile(argv.config, {
24
+ ignoreWarnings: false,
25
+ });
26
+ }
27
+ else {
28
+ Configuration.instance();
29
+ }
30
+ }, true)
20
31
  .command(deploy)
21
32
  .command(apps)
22
33
  .command(configure)
@@ -3,16 +3,14 @@ import fs from 'fs-extra';
3
3
  import { log } from '../log.js';
4
4
 
5
5
  class Configuration {
6
- workdir;
7
6
  static _instance;
8
7
  config = {};
9
- constructor(workdir) {
10
- this.workdir = workdir;
8
+ constructor() {
11
9
  // Try to read default config file
12
10
  this.setConfigFile("faable.json", { ignoreWarnings: true });
13
11
  }
14
12
  setConfigFile(file, options) {
15
- const config_file = path__default.join(this.workdir, file);
13
+ const config_file = path__default.join(process.cwd(), file);
16
14
  if (fs.existsSync(config_file)) {
17
15
  this.config = fs.readJSONSync(config_file);
18
16
  log.info(`Loaded configuration from: ${file}`);
@@ -23,14 +21,17 @@ class Configuration {
23
21
  }
24
22
  }
25
23
  }
26
- static instance(workdir) {
24
+ static instance() {
27
25
  if (!Configuration._instance) {
28
- Configuration._instance = new Configuration(workdir);
26
+ Configuration._instance = new Configuration();
29
27
  }
30
28
  return Configuration._instance;
31
29
  }
32
- getConfigProperty(name, defaultValue) {
33
- return this.config[name] || defaultValue;
30
+ get startCommand() {
31
+ return this.config.startCommand || "npm run start";
32
+ }
33
+ get buildCommand() {
34
+ return this.config.buildCommand;
34
35
  }
35
36
  }
36
37
 
package/dist/log.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import pino from 'pino';
2
- import pretty from 'pino-pretty';
2
+ import 'pino-pretty';
3
3
 
4
- const log = pino(pretty({
5
- colorize: true,
6
- messageFormat: "{timestamp}{if runtime}⚙️:{runtime} - {end}{msg}",
7
- ignore: "runtime",
8
- singleLine: true,
9
- }));
4
+ const log = pino({
5
+ transport: {
6
+ target: "pino-pretty",
7
+ options: {
8
+ colorize: true,
9
+ },
10
+ },
11
+ });
10
12
 
11
13
  export { log };
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "fs-extra": "^11.1.0",
7
7
  "handlebars": "^4.7.7",
8
8
  "pino": "^8.11.0",
9
- "pino-pretty": "^11.0.0",
9
+ "pino-pretty": "^9.4.0",
10
10
  "promisify-child-process": "^4.1.1",
11
11
  "prompts": "^2.4.2",
12
12
  "ramda": "^0.29.0",
@@ -14,7 +14,7 @@
14
14
  "yaml": "^2.2.2",
15
15
  "yargs": "^17.6.2"
16
16
  },
17
- "version": "1.4.12",
17
+ "version": "1.5.0",
18
18
  "bin": {
19
19
  "faable": "bin/faable.js"
20
20
  },
@@ -1,10 +0,0 @@
1
- import path__default from 'path';
2
- import fs from 'fs-extra';
3
-
4
- const builder = async (ctx) => {
5
- const { app, workdir } = ctx;
6
- const f = path__default.join(path__default.resolve(workdir), "Dockerfile");
7
- return { dockerfile: (await fs.readFile(f)).toString() };
8
- };
9
-
10
- export { builder, builder as default };
@@ -1,17 +0,0 @@
1
- const builders = {
2
- node: () => import('./node/index.js'),
3
- python: () => import('./python/index.js'),
4
- docker: () => import('./docker/index.js'),
5
- };
6
- const import_builder = async (runtime_name) => {
7
- try {
8
- let builder_module = await builders[runtime_name]();
9
- return builder_module.default;
10
- }
11
- catch (e) {
12
- console.log(e);
13
- throw new Error(`Builder import error for ${runtime_name}`);
14
- }
15
- };
16
-
17
- export { import_builder };
@@ -1,25 +0,0 @@
1
- import fs from 'fs-extra';
2
- import path__default from 'path';
3
-
4
- const analyze_package = async (ctx) => {
5
- const { log, workdir } = ctx;
6
- const node_modules_dir = path__default.join(path__default.resolve(workdir), "node_modules");
7
- const installedModules = await fs.pathExists(node_modules_dir);
8
- if (!installedModules) {
9
- throw new Error("node_modules not found, please install packages first");
10
- }
11
- const package_file = path__default.join(path__default.resolve(workdir), "package.json");
12
- const pkg = await fs.readJSON(package_file);
13
- // Detect deployment type
14
- let type = "node";
15
- if (pkg.dependencies["next"]) {
16
- type = "next";
17
- log.info(`✅ Next.js ⚡️ project detected`);
18
- }
19
- return {
20
- pkg,
21
- type,
22
- };
23
- };
24
-
25
- export { analyze_package };
@@ -1,27 +0,0 @@
1
- import { cmd } from '../../lib/cmd.js';
2
-
3
- const build_project = async (ctx, nodeCtx) => {
4
- const { log, config, workdir } = ctx;
5
- // Check if exists any type of builc command
6
- let build_command = config.getConfigProperty("buildCommand", process.env.FAABLE_NPM_BUILD_COMMAND);
7
- const build_script_name = config.getConfigProperty("buildScript", "build");
8
- const build_script = nodeCtx.pkg.scripts[build_script_name];
9
- // No build command but build script
10
- if (!build_command && build_script) {
11
- build_command = `npm run ${build_script_name}`;
12
- }
13
- if (build_command) {
14
- log.info(`✅ Build command detected. Running "${build_command}"`);
15
- const timeout = 1000 * 60 * 100; // 100 minute timeout
16
- await cmd(build_command, {
17
- timeout,
18
- cwd: workdir,
19
- enableOutput: true,
20
- });
21
- }
22
- else {
23
- log.info(`No build script in package.json`);
24
- }
25
- };
26
-
27
- export { build_project };
@@ -1,31 +0,0 @@
1
- import fs from 'fs-extra';
2
- import path__default from 'path';
3
- import { cmd } from '../../lib/cmd.js';
4
-
5
- const engine_version = async (ctx) => {
6
- const { workdir, log } = ctx;
7
- const packageJSONFile = path__default.join(workdir, "package.json");
8
- // Check we have a valid name
9
- const { name, engines } = fs.readJSONSync(packageJSONFile);
10
- if (!name) {
11
- throw new Error("Missing name in package.json");
12
- }
13
- // Use engines.node if found
14
- let version = "18.19.0";
15
- if (engines?.node) {
16
- try {
17
- const check_cmd = `npm view node@"${engines.node}" version | tail -n 1 | cut -d "'" -f2`;
18
- const out = await cmd(check_cmd);
19
- version = out.stdout.toString().trim();
20
- log.info(`✅ Engine "${engines.node}" from package.json resolved to node@${version}`);
21
- }
22
- catch (e) {
23
- throw new Error(`Node version is not valid (${engines.node})`);
24
- }
25
- }
26
- return {
27
- version,
28
- };
29
- };
30
-
31
- export { engine_version };
@@ -1,26 +0,0 @@
1
- import { prepare_dockerfile } from './prepare_dockerfile.js';
2
- import { analyze_package } from './analyze_package.js';
3
- import { build_project } from './build_project.js';
4
- import { engine_version } from './engine_version.js';
5
-
6
- const builder = async (ctx) => {
7
- // log.info(`🚀 Build Toolchain ${app.name} [${app.id}]`);
8
- const { version } = await engine_version(ctx);
9
- // Analyze package.json to check if build is needed
10
- const nodeCtx = await analyze_package(ctx);
11
- await build_project(ctx, nodeCtx);
12
- // Bundle project inside a docker image
13
- const { dockerfile } = await prepare_dockerfile(ctx, {
14
- template_context: {
15
- from: `node:${version}`,
16
- },
17
- });
18
- return {
19
- dockerfile,
20
- params: {
21
- type: nodeCtx.type,
22
- },
23
- };
24
- };
25
-
26
- export { builder, builder as default };
@@ -1,17 +0,0 @@
1
- import fs from 'fs-extra';
2
- import path__default from 'path';
3
- import { prepare_dockerfile } from './prepare_dockerfile.js';
4
-
5
- const builder = async (ctx) => {
6
- const { workdir, log } = ctx;
7
- const hasRequirements = fs.existsSync(path__default.join(path__default.resolve(workdir), "requirements.txt"));
8
- if (!hasRequirements) {
9
- throw new Error(`Missing requirements.txt`);
10
- }
11
- const { dockerfile } = await prepare_dockerfile(ctx);
12
- return {
13
- dockerfile,
14
- };
15
- };
16
-
17
- export { builder, builder as default };
@@ -1,40 +0,0 @@
1
- import fs from 'fs-extra';
2
- import Handlebars from 'handlebars';
3
- import * as path from 'path';
4
- import { fileURLToPath } from 'url';
5
-
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = path.dirname(__filename);
8
- const templates_dir = path.join(__dirname, "templates");
9
- const dockerfile = fs.readFileSync(`${templates_dir}/Dockerfile`).toString();
10
- const entrypoint = fs
11
- .readFileSync(`${templates_dir}/entrypoint.sh`)
12
- .toString("utf-8");
13
- Handlebars.registerHelper("escape", function (variable) {
14
- //const escaped_quotes = variable.replace(/(['"])/g, "\\$1");
15
- const escaped_lines = variable
16
- .replace(/(['`\\])/g, "\\$1")
17
- .replace(/([$])/g, "\\$1");
18
- return escaped_lines.split("\n").join("\\n");
19
- //return escaped_lines.split("\n").join("\\n");
20
- });
21
- // Docker template file
22
- const docker_template = Handlebars.compile(dockerfile);
23
- const entrypoint_template = Handlebars.compile(entrypoint);
24
- const prepare_dockerfile = async (ctx, params = {}) => {
25
- const { app, workdir, log, config } = ctx;
26
- const entrypoint_custom = entrypoint_template(params);
27
- const start_command = config.getConfigProperty("startCommand");
28
- if (!start_command) {
29
- throw new Error(`Missing start command configuration`);
30
- }
31
- log.info(`✅ Start command set to "${start_command}"`);
32
- const dockerfile = docker_template({
33
- ...params,
34
- entry_script: entrypoint_custom,
35
- start_command,
36
- });
37
- return { dockerfile };
38
- };
39
-
40
- export { prepare_dockerfile };
@@ -1,26 +0,0 @@
1
- FROM python:3.9-slim
2
-
3
- RUN apt-get update && apt-get install -y locales locales-all && rm -rf /var/lib/apt/lists/*
4
-
5
- RUN sed -i '/es_ES.UTF-8/s/^# //g' /etc/locale.gen && \
6
- locale-gen
7
-
8
- ENV LANG es_ES.UTF-8
9
- ENV LANGUAGE es_ES:es
10
- ENV LC_ALL es_ES.UTF-8
11
-
12
- ENV PORT=80
13
- ENV START_COMMAND="{{start_command}}"
14
-
15
- WORKDIR /app
16
-
17
- COPY requirements.txt .
18
-
19
- RUN pip install --no-cache-dir -r requirements.txt
20
-
21
- COPY . .
22
-
23
- # Entrypoint stript
24
- RUN echo '{{{escape entry_script}}}' >> entrypoint.sh
25
-
26
- CMD ["/bin/sh", "./entrypoint.sh"]
@@ -1,7 +0,0 @@
1
- #!/bin/sh
2
-
3
- PYTHON_VERSION=$(python --version)
4
- PIP_VERSION=$(pip --version)
5
-
6
- echo "Faable Cloud · [$PYTHON_VERSION] [$PIP_VERSION]"
7
- eval $START_COMMAND
@@ -1,19 +0,0 @@
1
- import fs from 'fs-extra';
2
- import path__default from 'path';
3
-
4
- const strategy_python = async (workdir) => {
5
- const runtime_config = path__default.join(workdir, "runtime.txt");
6
- // Select runtime based on config
7
- if (fs.existsSync(runtime_config)) {
8
- const runtime_data = fs.readFileSync(runtime_config).toString();
9
- if (!runtime_data.startsWith("python-")) {
10
- throw new Error("runtime.txt must have runtime format with python-<version>");
11
- }
12
- runtime_data.split("-")[1];
13
- }
14
- return {
15
- runtime: "python",
16
- };
17
- };
18
-
19
- export { strategy_python };