@rulebricks/cli 2.1.6 → 2.3.1
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/README.md +75 -14
- package/cluster-setup/aws/README.md +123 -0
- package/cluster-setup/aws/check-aws-access.sh +242 -0
- package/cluster-setup/aws/parameters.json +13 -0
- package/cluster-setup/aws/rulebricks-cluster.cfn.yaml +355 -0
- package/cluster-setup/azure/README.md +141 -0
- package/cluster-setup/azure/check-aks-prereqs.sh +276 -0
- package/cluster-setup/azure/parameters.json +30 -0
- package/cluster-setup/azure/rulebricks-cluster.bicep +546 -0
- package/cluster-setup/gcp/README.md +189 -0
- package/cluster-setup/gcp/check-gke-prereqs.sh +260 -0
- package/dist/commands/backup.d.ts +5 -0
- package/dist/commands/backup.js +104 -0
- package/dist/commands/deploy.d.ts +3 -1
- package/dist/commands/deploy.js +226 -326
- package/dist/commands/destroy.d.ts +1 -1
- package/dist/commands/destroy.js +73 -123
- package/dist/commands/init.d.ts +5 -1
- package/dist/commands/init.js +78 -47
- package/dist/commands/list.d.ts +1 -0
- package/dist/commands/list.js +74 -0
- package/dist/commands/open.d.ts +1 -1
- package/dist/commands/open.js +4 -12
- package/dist/commands/redeploy.d.ts +6 -0
- package/dist/commands/redeploy.js +310 -0
- package/dist/commands/restore.d.ts +5 -0
- package/dist/commands/restore.js +338 -0
- package/dist/commands/status.js +62 -49
- package/dist/commands/upgrade.js +74 -51
- package/dist/components/DNSWaitScreen.d.ts +5 -1
- package/dist/components/DNSWaitScreen.js +47 -41
- package/dist/components/Wizard/WizardContext.d.ts +174 -29
- package/dist/components/Wizard/WizardContext.js +896 -91
- package/dist/components/Wizard/steps/CloudProviderStep.js +192 -102
- package/dist/components/Wizard/steps/DomainStep.js +5 -24
- package/dist/components/Wizard/steps/ExternalServicesStep.d.ts +6 -0
- package/dist/components/Wizard/steps/ExternalServicesStep.js +645 -0
- package/dist/components/Wizard/steps/FeatureConfigStep.d.ts +2 -1
- package/dist/components/Wizard/steps/FeatureConfigStep.js +959 -248
- package/dist/components/Wizard/steps/FeaturesStep.js +31 -35
- package/dist/components/Wizard/steps/ObservabilityStep.d.ts +6 -0
- package/dist/components/Wizard/steps/ObservabilityStep.js +137 -0
- package/dist/components/Wizard/steps/ReviewStep.d.ts +2 -1
- package/dist/components/Wizard/steps/ReviewStep.js +56 -7
- package/dist/components/Wizard/steps/StorageStep.d.ts +9 -0
- package/dist/components/Wizard/steps/StorageStep.js +592 -0
- package/dist/components/Wizard/steps/SupabaseCredentialsStep.js +20 -21
- package/dist/components/Wizard/steps/VersionStep.js +45 -23
- package/dist/components/Wizard/steps/index.d.ts +3 -3
- package/dist/components/Wizard/steps/index.js +3 -3
- package/dist/components/common/CommandApproval.d.ts +12 -0
- package/dist/components/common/CommandApproval.js +91 -0
- package/dist/components/common/DeploymentPicker.d.ts +14 -0
- package/dist/components/common/DeploymentPicker.js +16 -0
- package/dist/components/common/index.d.ts +2 -0
- package/dist/components/common/index.js +2 -0
- package/dist/index.js +94 -62
- package/dist/lib/cloudCli.d.ts +134 -63
- package/dist/lib/cloudCli.js +512 -220
- package/dist/lib/clusterSetupDefaults.d.ts +30 -0
- package/dist/lib/clusterSetupDefaults.js +64 -0
- package/dist/lib/commandApproval.d.ts +26 -0
- package/dist/lib/commandApproval.js +114 -0
- package/dist/lib/config.d.ts +12 -10
- package/dist/lib/config.js +91 -33
- package/dist/lib/configFixtures.d.ts +5 -0
- package/dist/lib/configFixtures.js +513 -0
- package/dist/lib/deploymentHealth.d.ts +32 -0
- package/dist/lib/deploymentHealth.js +157 -0
- package/dist/lib/dns.d.ts +1 -1
- package/dist/lib/dns.js +19 -1
- package/dist/lib/dns.test.d.ts +1 -0
- package/dist/lib/dns.test.js +27 -0
- package/dist/lib/dockerHub.d.ts +12 -1
- package/dist/lib/dockerHub.js +18 -8
- package/dist/lib/helm.d.ts +4 -0
- package/dist/lib/helm.js +16 -0
- package/dist/lib/helmValues.d.ts +25 -0
- package/dist/lib/helmValues.js +1937 -259
- package/dist/lib/helmValues.test.d.ts +1 -0
- package/dist/lib/helmValues.test.js +966 -0
- package/dist/lib/htpasswd.d.ts +1 -0
- package/dist/lib/htpasswd.js +15 -0
- package/dist/lib/kubernetes.d.ts +126 -13
- package/dist/lib/kubernetes.js +624 -134
- package/dist/lib/secrets.d.ts +23 -0
- package/dist/lib/secrets.js +158 -0
- package/dist/lib/validateValues.d.ts +31 -0
- package/dist/lib/validateValues.js +253 -0
- package/dist/lib/versions.d.ts +82 -11
- package/dist/lib/versions.js +131 -31
- package/dist/lib/versions.test.d.ts +1 -0
- package/dist/lib/versions.test.js +81 -0
- package/dist/lib/wizardSteps.d.ts +14 -0
- package/dist/lib/wizardSteps.js +23 -0
- package/dist/lib/workloadIdentity.d.ts +26 -0
- package/dist/lib/workloadIdentity.js +323 -0
- package/dist/lib/workloadIdentity.test.d.ts +1 -0
- package/dist/lib/workloadIdentity.test.js +57 -0
- package/dist/types/index.d.ts +2152 -95
- package/dist/types/index.js +554 -286
- package/package.json +10 -4
- package/schema/values.schema.json +1934 -0
- package/dist/components/Wizard/steps/CredentialsStep.d.ts +0 -6
- package/dist/components/Wizard/steps/CredentialsStep.js +0 -22
- package/dist/components/Wizard/steps/DeploymentModeStep.d.ts +0 -5
- package/dist/components/Wizard/steps/DeploymentModeStep.js +0 -26
- package/dist/components/Wizard/steps/TierStep.d.ts +0 -6
- package/dist/components/Wizard/steps/TierStep.js +0 -29
- package/dist/lib/terraform.d.ts +0 -66
- package/dist/lib/terraform.js +0 -754
- package/terraform/aws/main.tf +0 -355
- package/terraform/azure/main.tf +0 -371
- package/terraform/gcp/main.tf +0 -407
package/dist/lib/dns.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export declare function getLoadBalancerAddress(namespace?: string): Promise<{
|
|
|
20
20
|
/**
|
|
21
21
|
* Gets all required DNS records for a deployment
|
|
22
22
|
*/
|
|
23
|
-
export declare function getRequiredDNSRecords(domain: string, loadBalancerAddress: string, loadBalancerType: "ip" | "hostname", selfHostedSupabase: boolean): DNSRecord[];
|
|
23
|
+
export declare function getRequiredDNSRecords(domain: string, loadBalancerAddress: string, loadBalancerType: "ip" | "hostname", selfHostedSupabase: boolean, builtInObservability?: boolean, observabilityHostname?: string, valkeyAdminIngress?: boolean, valkeyAdminHostname?: string): DNSRecord[];
|
|
24
24
|
/**
|
|
25
25
|
* Polls DNS records until they resolve or timeout
|
|
26
26
|
*/
|
package/dist/lib/dns.js
CHANGED
|
@@ -239,7 +239,7 @@ export async function getLoadBalancerAddress(namespace = DEFAULT_NAMESPACE) {
|
|
|
239
239
|
/**
|
|
240
240
|
* Gets all required DNS records for a deployment
|
|
241
241
|
*/
|
|
242
|
-
export function getRequiredDNSRecords(domain, loadBalancerAddress, loadBalancerType, selfHostedSupabase) {
|
|
242
|
+
export function getRequiredDNSRecords(domain, loadBalancerAddress, loadBalancerType, selfHostedSupabase, builtInObservability = false, observabilityHostname, valkeyAdminIngress = false, valkeyAdminHostname) {
|
|
243
243
|
const records = [
|
|
244
244
|
{
|
|
245
245
|
hostname: domain,
|
|
@@ -259,6 +259,24 @@ export function getRequiredDNSRecords(domain, loadBalancerAddress, loadBalancerT
|
|
|
259
259
|
required: true,
|
|
260
260
|
});
|
|
261
261
|
}
|
|
262
|
+
if (builtInObservability) {
|
|
263
|
+
records.push({
|
|
264
|
+
hostname: observabilityHostname || `observability.${domain}`,
|
|
265
|
+
type: loadBalancerType === "ip" ? "A" : "CNAME",
|
|
266
|
+
target: loadBalancerAddress,
|
|
267
|
+
verified: false,
|
|
268
|
+
required: true,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
if (valkeyAdminIngress) {
|
|
272
|
+
records.push({
|
|
273
|
+
hostname: valkeyAdminHostname || `valkey.${domain}`,
|
|
274
|
+
type: loadBalancerType === "ip" ? "A" : "CNAME",
|
|
275
|
+
target: loadBalancerAddress,
|
|
276
|
+
verified: false,
|
|
277
|
+
required: true,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
262
280
|
return records;
|
|
263
281
|
}
|
|
264
282
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { getRequiredDNSRecords } from "./dns.js";
|
|
4
|
+
test("manual DNS records include app, Supabase, and built-in observability", () => {
|
|
5
|
+
const records = getRequiredDNSRecords("az-p055.rulebricks.com", "4.236.203.25", "ip", true, true);
|
|
6
|
+
assert.deepEqual(records.map((record) => record.hostname), [
|
|
7
|
+
"az-p055.rulebricks.com",
|
|
8
|
+
"supabase.az-p055.rulebricks.com",
|
|
9
|
+
"observability.az-p055.rulebricks.com",
|
|
10
|
+
]);
|
|
11
|
+
assert.ok(records.every((record) => record.type === "A"));
|
|
12
|
+
assert.ok(records.every((record) => record.target === "4.236.203.25"));
|
|
13
|
+
});
|
|
14
|
+
test("manual DNS records omit observability when built-in observability is disabled", () => {
|
|
15
|
+
const records = getRequiredDNSRecords("az-p055.rulebricks.com", "example-lb.example.net", "hostname", true, false);
|
|
16
|
+
assert.deepEqual(records.map((record) => record.hostname), ["az-p055.rulebricks.com", "supabase.az-p055.rulebricks.com"]);
|
|
17
|
+
assert.ok(records.every((record) => record.type === "CNAME"));
|
|
18
|
+
});
|
|
19
|
+
test("manual DNS records include Valkey Admin ingress when enabled", () => {
|
|
20
|
+
const records = getRequiredDNSRecords("az-p055.rulebricks.com", "4.236.203.25", "ip", false, false, undefined, true);
|
|
21
|
+
assert.deepEqual(records.map((record) => record.hostname), ["az-p055.rulebricks.com", "valkey.az-p055.rulebricks.com"]);
|
|
22
|
+
});
|
|
23
|
+
test("manual DNS records use custom Valkey Admin hostname", () => {
|
|
24
|
+
const records = getRequiredDNSRecords("az-p055.rulebricks.com", "example-lb.example.net", "hostname", false, false, undefined, true, "redis-tools.example.com");
|
|
25
|
+
assert.deepEqual(records.map((record) => record.hostname), ["az-p055.rulebricks.com", "redis-tools.example.com"]);
|
|
26
|
+
assert.ok(records.every((record) => record.type === "CNAME"));
|
|
27
|
+
});
|
package/dist/lib/dockerHub.d.ts
CHANGED
|
@@ -14,8 +14,12 @@ export interface ImageTag {
|
|
|
14
14
|
lastUpdated: Date;
|
|
15
15
|
/** Image digest */
|
|
16
16
|
digest: string;
|
|
17
|
+
/** Manifest/image digests reported for this tag */
|
|
18
|
+
imageDigests: string[];
|
|
17
19
|
/** Full image size in bytes */
|
|
18
20
|
fullSize: number;
|
|
21
|
+
/** Architectures available in the tag's manifest list */
|
|
22
|
+
architectures: string[];
|
|
19
23
|
}
|
|
20
24
|
/**
|
|
21
25
|
* Formats the license key as a Docker PAT
|
|
@@ -36,7 +40,13 @@ export declare function authenticateDockerHub(licenseKey: string): Promise<strin
|
|
|
36
40
|
* @param pageSize - Number of tags to fetch per page (max 100)
|
|
37
41
|
* @returns Array of image tags sorted by last updated (newest first)
|
|
38
42
|
*/
|
|
39
|
-
export declare function fetchImageTags(repo: string, token: string, pageSize?: number): Promise<ImageTag[]>;
|
|
43
|
+
export declare function fetchImageTags(repo: string, token: string, pageSize?: number, tagFilter?: (tag: string) => boolean): Promise<ImageTag[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Checks if a tag looks like a valid semantic version
|
|
46
|
+
* Excludes "latest" and other non-numeric tags
|
|
47
|
+
*/
|
|
48
|
+
export declare function isValidVersionTag(tag: string): boolean;
|
|
49
|
+
export declare function isValidWorkerVersionTag(tag: string): boolean;
|
|
40
50
|
/**
|
|
41
51
|
* Fetches tags for both app and HPS repositories
|
|
42
52
|
*
|
|
@@ -46,6 +56,7 @@ export declare function fetchImageTags(repo: string, token: string, pageSize?: n
|
|
|
46
56
|
export declare function fetchAllImageTags(licenseKey: string): Promise<{
|
|
47
57
|
appTags: ImageTag[];
|
|
48
58
|
hpsTags: ImageTag[];
|
|
59
|
+
hpsWorkerTags: ImageTag[];
|
|
49
60
|
}>;
|
|
50
61
|
/**
|
|
51
62
|
* Normalizes a version string by removing leading 'v'
|
package/dist/lib/dockerHub.js
CHANGED
|
@@ -51,7 +51,7 @@ export async function authenticateDockerHub(licenseKey) {
|
|
|
51
51
|
* @param pageSize - Number of tags to fetch per page (max 100)
|
|
52
52
|
* @returns Array of image tags sorted by last updated (newest first)
|
|
53
53
|
*/
|
|
54
|
-
export async function fetchImageTags(repo, token, pageSize = 100) {
|
|
54
|
+
export async function fetchImageTags(repo, token, pageSize = 100, tagFilter = isValidVersionTag) {
|
|
55
55
|
const allTags = [];
|
|
56
56
|
let url = `${DOCKER_HUB_API}/repositories/${repo}/tags?page_size=${pageSize}`;
|
|
57
57
|
while (url) {
|
|
@@ -68,19 +68,25 @@ export async function fetchImageTags(repo, token, pageSize = 100) {
|
|
|
68
68
|
}
|
|
69
69
|
const data = await response.json();
|
|
70
70
|
for (const tag of data.results) {
|
|
71
|
-
|
|
72
|
-
if (!isValidVersionTag(tag.name)) {
|
|
71
|
+
if (!tagFilter(tag.name)) {
|
|
73
72
|
continue;
|
|
74
73
|
}
|
|
74
|
+
const imageDigests = Array.from(new Set([
|
|
75
|
+
tag.digest,
|
|
76
|
+
...(tag.images || []).map((image) => image.digest),
|
|
77
|
+
].filter(Boolean)));
|
|
75
78
|
allTags.push({
|
|
76
79
|
name: tag.name,
|
|
77
80
|
lastUpdated: new Date(tag.last_updated),
|
|
78
81
|
digest: tag.digest,
|
|
82
|
+
imageDigests,
|
|
79
83
|
fullSize: tag.full_size,
|
|
84
|
+
architectures: Array.from(new Set((tag.images || [])
|
|
85
|
+
.map((image) => image.architecture)
|
|
86
|
+
.filter(Boolean))),
|
|
80
87
|
});
|
|
81
88
|
}
|
|
82
|
-
|
|
83
|
-
url = data.next && allTags.length < 50 ? data.next : null;
|
|
89
|
+
url = data.next;
|
|
84
90
|
}
|
|
85
91
|
// Sort by last updated, newest first
|
|
86
92
|
allTags.sort((a, b) => b.lastUpdated.getTime() - a.lastUpdated.getTime());
|
|
@@ -90,7 +96,7 @@ export async function fetchImageTags(repo, token, pageSize = 100) {
|
|
|
90
96
|
* Checks if a tag looks like a valid semantic version
|
|
91
97
|
* Excludes "latest" and other non-numeric tags
|
|
92
98
|
*/
|
|
93
|
-
function isValidVersionTag(tag) {
|
|
99
|
+
export function isValidVersionTag(tag) {
|
|
94
100
|
// Exclude "latest" and similar non-versioned tags
|
|
95
101
|
if (tag === 'latest' || tag === 'dev' || tag === 'main' || tag === 'master') {
|
|
96
102
|
return false;
|
|
@@ -99,6 +105,9 @@ function isValidVersionTag(tag) {
|
|
|
99
105
|
const versionPattern = /^v?\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
100
106
|
return versionPattern.test(tag);
|
|
101
107
|
}
|
|
108
|
+
export function isValidWorkerVersionTag(tag) {
|
|
109
|
+
return /^worker-\d+\.\d+\.\d+(-[\w.]+)?$/.test(tag);
|
|
110
|
+
}
|
|
102
111
|
/**
|
|
103
112
|
* Fetches tags for both app and HPS repositories
|
|
104
113
|
*
|
|
@@ -107,11 +116,12 @@ function isValidVersionTag(tag) {
|
|
|
107
116
|
*/
|
|
108
117
|
export async function fetchAllImageTags(licenseKey) {
|
|
109
118
|
const token = await authenticateDockerHub(licenseKey);
|
|
110
|
-
const [appTags, hpsTags] = await Promise.all([
|
|
119
|
+
const [appTags, hpsTags, hpsWorkerTags] = await Promise.all([
|
|
111
120
|
fetchImageTags('rulebricks/app', token),
|
|
112
121
|
fetchImageTags('rulebricks/hps', token),
|
|
122
|
+
fetchImageTags('rulebricks/hps', token, 100, isValidWorkerVersionTag),
|
|
113
123
|
]);
|
|
114
|
-
return { appTags, hpsTags };
|
|
124
|
+
return { appTags, hpsTags, hpsWorkerTags };
|
|
115
125
|
}
|
|
116
126
|
/**
|
|
117
127
|
* Normalizes a version string by removing leading 'v'
|
package/dist/lib/helm.d.ts
CHANGED
|
@@ -15,6 +15,10 @@ export declare function fetchChartVersions(): Promise<ChartVersion[]>;
|
|
|
15
15
|
* Gets the currently installed chart version for a deployment
|
|
16
16
|
*/
|
|
17
17
|
export declare function getInstalledVersion(releaseName: string, namespace: string): Promise<string | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Gets the installed Helm chart version for a deployment.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getInstalledChartVersion(releaseName: string, namespace: string): Promise<string | null>;
|
|
18
22
|
/**
|
|
19
23
|
* Installs the Rulebricks Helm chart (use installOrUpgradeChart for idempotent operations)
|
|
20
24
|
*/
|
package/dist/lib/helm.js
CHANGED
|
@@ -101,6 +101,22 @@ export async function getInstalledVersion(releaseName, namespace) {
|
|
|
101
101
|
return null;
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Gets the installed Helm chart version for a deployment.
|
|
106
|
+
*/
|
|
107
|
+
export async function getInstalledChartVersion(releaseName, namespace) {
|
|
108
|
+
try {
|
|
109
|
+
const { stdout } = await execa("helm", ["list", "-n", namespace, "-f", `^${releaseName}$`, "-o", "json"], { timeout: 15000 });
|
|
110
|
+
const releases = JSON.parse(stdout);
|
|
111
|
+
if (releases.length === 0) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
return releases[0].chart.split("-").pop() || null;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
104
120
|
/**
|
|
105
121
|
* Installs the Rulebricks Helm chart (use installOrUpgradeChart for idempotent operations)
|
|
106
122
|
*/
|
package/dist/lib/helmValues.d.ts
CHANGED
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
import { DeploymentConfig } from "../types/index.js";
|
|
2
2
|
interface GenerateOptions {
|
|
3
3
|
tlsEnabled?: boolean;
|
|
4
|
+
secretMode?: "k8s" | "inline";
|
|
4
5
|
}
|
|
6
|
+
export declare function deploymentSecretNames(config: DeploymentConfig): {
|
|
7
|
+
app: string;
|
|
8
|
+
db: string;
|
|
9
|
+
dbBootstrap: string;
|
|
10
|
+
jwt: string;
|
|
11
|
+
dashboard: string;
|
|
12
|
+
realtime: string;
|
|
13
|
+
smtp: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function signSupabaseJwt(role: "anon" | "service_role", secret: string): string;
|
|
16
|
+
export declare function deriveRealtimeSecrets(jwtSecret: string): {
|
|
17
|
+
secretKeyBase: string;
|
|
18
|
+
dbEncKey: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Builds Helm values from the deployment configuration.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildHelmValues(config: DeploymentConfig, options?: GenerateOptions): Record<string, unknown>;
|
|
24
|
+
/**
|
|
25
|
+
* Rewrites generated values for k8s secret mode: sets the chart's *.secretRef
|
|
26
|
+
* seams to the CLI-created Secret names and removes inline plaintext secrets so
|
|
27
|
+
* none are persisted to values.yaml or the Helm release.
|
|
28
|
+
*/
|
|
29
|
+
export declare function redactSecretsToRefs(values: Record<string, unknown>, config: DeploymentConfig): Record<string, unknown>;
|
|
5
30
|
/**
|
|
6
31
|
* Generates Helm values from the deployment configuration
|
|
7
32
|
*/
|