@faable/faable 1.5.29 → 1.5.30
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.
package/dist/api/context.js
CHANGED
|
@@ -7,12 +7,8 @@ import { CredentialsStore } from '../lib/CredentialsStore.js';
|
|
|
7
7
|
|
|
8
8
|
const context = async () => {
|
|
9
9
|
let api;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const apikey = process.env.FAABLE_APIKEY;
|
|
13
|
-
api = FaableApi.create({ authStrategy: apikey_strategy, auth: { apikey } });
|
|
14
|
-
}
|
|
15
|
-
else if (process.env.FAABLE_TOKEN) {
|
|
10
|
+
// Auth resolution: FAABLE_TOKEN → OIDC (CI) → local `faable login` credentials.
|
|
11
|
+
if (process.env.FAABLE_TOKEN) {
|
|
16
12
|
// Token in environment
|
|
17
13
|
const token = process.env.FAABLE_TOKEN;
|
|
18
14
|
api = FaableApi.create({ authStrategy: bearer_strategy, auth: { token } });
|
|
@@ -1,12 +1,34 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
1
2
|
import { create_base_client } from '../base_client.js';
|
|
2
3
|
|
|
3
4
|
const exchangeGithubOidcToken = async (gh_token) => {
|
|
4
5
|
const client = create_base_client();
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
try {
|
|
7
|
+
const res = await client.post("/auth/github-oidc", {
|
|
8
|
+
token: gh_token
|
|
9
|
+
});
|
|
10
|
+
const { access_token, app_id } = res.data;
|
|
11
|
+
return { access_token, app_id };
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
if (axios.isAxiosError(err)) {
|
|
15
|
+
const status = err.response?.status;
|
|
16
|
+
const serverMessage = err.response?.data?.message;
|
|
17
|
+
// No app is linked to this repository — turn the cryptic 404 into an
|
|
18
|
+
// actionable next step.
|
|
19
|
+
if (status === 404) {
|
|
20
|
+
throw new Error('No app linked to this repository. Run "faable link" locally to link it, ' +
|
|
21
|
+
"or link it from the dashboard (https://dashboard.faable.com).");
|
|
22
|
+
}
|
|
23
|
+
// Monorepo: several apps are linked to the same repository.
|
|
24
|
+
if (status === 400) {
|
|
25
|
+
throw new Error(serverMessage ||
|
|
26
|
+
"This repository has multiple linked apps. Specify which one with `faable deploy <app_id>`.");
|
|
27
|
+
}
|
|
28
|
+
throw new Error(`Faable OIDC token exchange failed (${status ?? "network error"})${serverMessage ? `: ${serverMessage}` : ""}`);
|
|
29
|
+
}
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
10
32
|
};
|
|
11
33
|
const oidc_strategy = (config) => {
|
|
12
34
|
const { idToken } = config;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { context } from '../../api/context.js';
|
|
2
2
|
import { cmd } from '../../lib/cmd.js';
|
|
3
|
+
import { Configuration } from '../../lib/Configuration.js';
|
|
3
4
|
import { log } from '../../log.js';
|
|
4
5
|
import { check_environment } from './check_environment.js';
|
|
5
6
|
import { git_context } from './git_context.js';
|
|
@@ -30,9 +31,13 @@ const deploy = {
|
|
|
30
31
|
const { api } = ctx;
|
|
31
32
|
// Resolve runtime
|
|
32
33
|
const { runtime } = await runtime_detection(workdir);
|
|
33
|
-
|
|
34
|
+
// app_id resolution (the user never has to look one up):
|
|
35
|
+
// 1. explicit positional (monorepo escape hatch)
|
|
36
|
+
// 2. OIDC in CI — the backend resolves the app from the linked repository
|
|
37
|
+
// 3. locally — the app saved by `faable link` in faable.json
|
|
38
|
+
const app_id = args.app_id || ctx.appId || Configuration.instance().app_id;
|
|
34
39
|
if (!app_id) {
|
|
35
|
-
throw new Error('
|
|
40
|
+
throw new Error('No app linked to this repository. Run "faable link" to link it (or link it from the dashboard).');
|
|
36
41
|
}
|
|
37
42
|
const app = await api.getApp(app_id);
|
|
38
43
|
// Check if we can build docker images
|
|
@@ -24,14 +24,10 @@ const getGitRemoteUrl = async (workdir) => {
|
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
const link = {
|
|
27
|
-
command: "link
|
|
27
|
+
command: "link",
|
|
28
28
|
describe: "Link the local repository with a Faable app",
|
|
29
29
|
builder: (yargs) => {
|
|
30
30
|
return yargs
|
|
31
|
-
.positional("app_id", {
|
|
32
|
-
type: "string",
|
|
33
|
-
description: "app_id to link this repository",
|
|
34
|
-
})
|
|
35
31
|
.option("workdir", {
|
|
36
32
|
alias: "w",
|
|
37
33
|
type: "string",
|
|
@@ -41,7 +37,14 @@ const link = {
|
|
|
41
37
|
},
|
|
42
38
|
handler: async (args) => {
|
|
43
39
|
const workdir = args.workdir || process.cwd();
|
|
44
|
-
|
|
40
|
+
// `faable link <app_id>` is deprecated. Linking is now fully interactive and
|
|
41
|
+
// the repository is auto-detected from the current folder — users never need
|
|
42
|
+
// to look up an app_id. Warn if an extra positional was passed and ignore it.
|
|
43
|
+
const stray = (args._ ?? []).slice(1);
|
|
44
|
+
if (stray.length > 0) {
|
|
45
|
+
log.warn('Passing an app_id to "faable link" is deprecated and ignored. ' +
|
|
46
|
+
'Just run "faable link" and select the app from the list.');
|
|
47
|
+
}
|
|
45
48
|
const config = Configuration.instance();
|
|
46
49
|
if (config.app_id) {
|
|
47
50
|
log.info(`This repository is already linked to app: "${config.app_slug}" (${config.app_id})`);
|
|
@@ -60,26 +63,20 @@ const link = {
|
|
|
60
63
|
const { api } = await context();
|
|
61
64
|
log.info("Checking local git repository...");
|
|
62
65
|
const gitUrl = await getGitRemoteUrl(workdir);
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
log.error("No apps found in your account. Create one first at https://faable.com");
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
selectedApp = await prompts({
|
|
71
|
-
type: "select",
|
|
72
|
-
name: "selectedApp",
|
|
73
|
-
message: "Select the Faable app to link with this repository:",
|
|
74
|
-
choices: apps.map((app) => ({
|
|
75
|
-
title: `${app.name} (${app.url})`,
|
|
76
|
-
value: app,
|
|
77
|
-
})),
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
selectedApp = await api.getApp(app_id);
|
|
66
|
+
const apps = await api.list();
|
|
67
|
+
if (apps.length === 0) {
|
|
68
|
+
log.error("No apps found in your account. Create one first at https://faable.com");
|
|
69
|
+
return;
|
|
82
70
|
}
|
|
71
|
+
const { selectedApp } = await prompts({
|
|
72
|
+
type: "select",
|
|
73
|
+
name: "selectedApp",
|
|
74
|
+
message: "Select the Faable app to link with this repository:",
|
|
75
|
+
choices: apps.map((app) => ({
|
|
76
|
+
title: `${app.name} (${app.url})`,
|
|
77
|
+
value: app,
|
|
78
|
+
})),
|
|
79
|
+
});
|
|
83
80
|
if (!selectedApp) {
|
|
84
81
|
log.info("Link cancelled.");
|
|
85
82
|
return;
|