@tachyon-gg/railway-deploy 0.2.0 → 0.2.2
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/index.js +248 -251
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -23745,6 +23745,48 @@ var require_graphql2 = __commonJS((exports) => {
|
|
|
23745
23745
|
var _index6 = require_utilities();
|
|
23746
23746
|
});
|
|
23747
23747
|
|
|
23748
|
+
// node_modules/fast-deep-equal/index.js
|
|
23749
|
+
var require_fast_deep_equal = __commonJS((exports, module) => {
|
|
23750
|
+
module.exports = function equal(a, b) {
|
|
23751
|
+
if (a === b)
|
|
23752
|
+
return true;
|
|
23753
|
+
if (a && b && typeof a == "object" && typeof b == "object") {
|
|
23754
|
+
if (a.constructor !== b.constructor)
|
|
23755
|
+
return false;
|
|
23756
|
+
var length, i, keys;
|
|
23757
|
+
if (Array.isArray(a)) {
|
|
23758
|
+
length = a.length;
|
|
23759
|
+
if (length != b.length)
|
|
23760
|
+
return false;
|
|
23761
|
+
for (i = length;i-- !== 0; )
|
|
23762
|
+
if (!equal(a[i], b[i]))
|
|
23763
|
+
return false;
|
|
23764
|
+
return true;
|
|
23765
|
+
}
|
|
23766
|
+
if (a.constructor === RegExp)
|
|
23767
|
+
return a.source === b.source && a.flags === b.flags;
|
|
23768
|
+
if (a.valueOf !== Object.prototype.valueOf)
|
|
23769
|
+
return a.valueOf() === b.valueOf();
|
|
23770
|
+
if (a.toString !== Object.prototype.toString)
|
|
23771
|
+
return a.toString() === b.toString();
|
|
23772
|
+
keys = Object.keys(a);
|
|
23773
|
+
length = keys.length;
|
|
23774
|
+
if (length !== Object.keys(b).length)
|
|
23775
|
+
return false;
|
|
23776
|
+
for (i = length;i-- !== 0; )
|
|
23777
|
+
if (!Object.prototype.hasOwnProperty.call(b, keys[i]))
|
|
23778
|
+
return false;
|
|
23779
|
+
for (i = length;i-- !== 0; ) {
|
|
23780
|
+
var key = keys[i];
|
|
23781
|
+
if (!equal(a[key], b[key]))
|
|
23782
|
+
return false;
|
|
23783
|
+
}
|
|
23784
|
+
return true;
|
|
23785
|
+
}
|
|
23786
|
+
return a !== a && b !== b;
|
|
23787
|
+
};
|
|
23788
|
+
});
|
|
23789
|
+
|
|
23748
23790
|
// node_modules/commander/esm.mjs
|
|
23749
23791
|
var import__ = __toESM(require_commander(), 1);
|
|
23750
23792
|
var {
|
|
@@ -37549,19 +37591,21 @@ ${issues}`);
|
|
|
37549
37591
|
// src/config/variables.ts
|
|
37550
37592
|
var import_dotenv = __toESM(require_main(), 1);
|
|
37551
37593
|
import { readFileSync } from "fs";
|
|
37552
|
-
function resolveEnvVars(variables, env = process.env) {
|
|
37594
|
+
function resolveEnvVars(variables, env = process.env, lenient = false) {
|
|
37553
37595
|
const resolved = {};
|
|
37554
37596
|
for (const [key, value] of Object.entries(variables)) {
|
|
37555
37597
|
if (value === null)
|
|
37556
37598
|
continue;
|
|
37557
|
-
resolved[key] = resolveEnvVarString(value, env);
|
|
37599
|
+
resolved[key] = resolveEnvVarString(value, env, lenient);
|
|
37558
37600
|
}
|
|
37559
37601
|
return resolved;
|
|
37560
37602
|
}
|
|
37561
|
-
function resolveEnvVarString(input, env = process.env) {
|
|
37562
|
-
return input.replace(/\$\{(?!\{)([^}]+)\}/g, (
|
|
37603
|
+
function resolveEnvVarString(input, env = process.env, lenient = false) {
|
|
37604
|
+
return input.replace(/\$\{(?!\{)([^}]+)\}/g, (match, name) => {
|
|
37563
37605
|
const value = env[name];
|
|
37564
37606
|
if (value === undefined) {
|
|
37607
|
+
if (lenient)
|
|
37608
|
+
return match;
|
|
37565
37609
|
throw new Error(`Environment variable "${name}" is not set (referenced as \${${name}})`);
|
|
37566
37610
|
}
|
|
37567
37611
|
return value;
|
|
@@ -37590,7 +37634,7 @@ function normalizeDomains(domains) {
|
|
|
37590
37634
|
return [];
|
|
37591
37635
|
return domains.map(normalizeDomainEntry);
|
|
37592
37636
|
}
|
|
37593
|
-
function loadEnvironmentConfig(envFilePath) {
|
|
37637
|
+
function loadEnvironmentConfig(envFilePath, options) {
|
|
37594
37638
|
const absPath = resolve(envFilePath);
|
|
37595
37639
|
if (!existsSync(absPath)) {
|
|
37596
37640
|
throw new Error(`Config file not found: ${absPath}`);
|
|
@@ -37612,14 +37656,15 @@ function loadEnvironmentConfig(envFilePath) {
|
|
|
37612
37656
|
const config2 = parsed;
|
|
37613
37657
|
const services = {};
|
|
37614
37658
|
const deletedVars = {};
|
|
37659
|
+
const lenient = options?.lenient ?? false;
|
|
37615
37660
|
for (const [name, entry] of Object.entries(config2.services)) {
|
|
37616
|
-
const { service, deleted } = resolveService(name, entry, envDir);
|
|
37661
|
+
const { service, deleted } = resolveService(name, entry, envDir, lenient);
|
|
37617
37662
|
services[name] = service;
|
|
37618
37663
|
if (deleted.length > 0) {
|
|
37619
37664
|
deletedVars[name] = deleted;
|
|
37620
37665
|
}
|
|
37621
37666
|
}
|
|
37622
|
-
const resolvedSharedVars = config2.shared_variables ? resolveEnvVars(config2.shared_variables) : {};
|
|
37667
|
+
const resolvedSharedVars = config2.shared_variables ? resolveEnvVars(config2.shared_variables, process.env, lenient) : {};
|
|
37623
37668
|
const deletedSharedVars = config2.shared_variables ? getDeletedVariables(config2.shared_variables) : [];
|
|
37624
37669
|
const buckets = {};
|
|
37625
37670
|
if (config2.buckets) {
|
|
@@ -37641,7 +37686,7 @@ function loadEnvironmentConfig(envFilePath) {
|
|
|
37641
37686
|
environmentName: config2.environment
|
|
37642
37687
|
};
|
|
37643
37688
|
}
|
|
37644
|
-
function resolveService(name, entry, envDir) {
|
|
37689
|
+
function resolveService(name, entry, envDir, lenient = false) {
|
|
37645
37690
|
let template;
|
|
37646
37691
|
if (entry.template) {
|
|
37647
37692
|
const templatePath = resolve(envDir, entry.template);
|
|
@@ -37708,9 +37753,9 @@ function resolveService(name, entry, envDir) {
|
|
|
37708
37753
|
...entry.variables || {}
|
|
37709
37754
|
};
|
|
37710
37755
|
const deleted = getDeletedVariables(mergedVars);
|
|
37711
|
-
const resolvedVars = resolveEnvVars(mergedVars);
|
|
37756
|
+
const resolvedVars = resolveEnvVars(mergedVars, process.env, lenient);
|
|
37712
37757
|
const resolvedDomainsRaw = domains.map((d) => ({
|
|
37713
|
-
domain: resolveEnvVarString(d.domain),
|
|
37758
|
+
domain: resolveEnvVarString(d.domain, process.env, lenient),
|
|
37714
37759
|
...d.targetPort !== undefined ? { targetPort: d.targetPort } : {}
|
|
37715
37760
|
}));
|
|
37716
37761
|
const seenDomains = new Set;
|
|
@@ -37776,8 +37821,8 @@ function resolveService(name, entry, envDir) {
|
|
|
37776
37821
|
service.checkSuites = checkSuites;
|
|
37777
37822
|
if (registryCredentials) {
|
|
37778
37823
|
service.registryCredentials = {
|
|
37779
|
-
username: resolveEnvVarString(registryCredentials.username),
|
|
37780
|
-
password: resolveEnvVarString(registryCredentials.password)
|
|
37824
|
+
username: resolveEnvVarString(registryCredentials.username, process.env, lenient),
|
|
37825
|
+
password: resolveEnvVarString(registryCredentials.password, process.env, lenient)
|
|
37781
37826
|
};
|
|
37782
37827
|
}
|
|
37783
37828
|
if (railwayDomain !== undefined) {
|
|
@@ -38853,62 +38898,162 @@ function isSensitive(key) {
|
|
|
38853
38898
|
function maskValue(key, value) {
|
|
38854
38899
|
return isSensitive(key) ? "***" : value;
|
|
38855
38900
|
}
|
|
38856
|
-
function
|
|
38901
|
+
function describeChange(change) {
|
|
38857
38902
|
switch (change.type) {
|
|
38858
|
-
case "create-service":
|
|
38859
|
-
|
|
38903
|
+
case "create-service": {
|
|
38904
|
+
const src = change.source?.image || change.source?.repo || "empty";
|
|
38905
|
+
const details = [src];
|
|
38906
|
+
if (change.branch)
|
|
38907
|
+
details.push(`branch: ${change.branch}`);
|
|
38908
|
+
if (change.volume)
|
|
38909
|
+
details.push(`volume: ${change.volume.mount}`);
|
|
38910
|
+
if (change.cronSchedule)
|
|
38911
|
+
details.push(`cron: ${change.cronSchedule}`);
|
|
38912
|
+
return {
|
|
38913
|
+
category: "Services",
|
|
38914
|
+
action: "create",
|
|
38915
|
+
summary: `${change.name} (${details.join(", ")})`
|
|
38916
|
+
};
|
|
38917
|
+
}
|
|
38860
38918
|
case "delete-service":
|
|
38861
|
-
return
|
|
38862
|
-
|
|
38863
|
-
|
|
38864
|
-
|
|
38865
|
-
|
|
38866
|
-
case "upsert-shared-variables":
|
|
38867
|
-
return `upsert-shared-variables (${Object.keys(change.variables).length} vars)`;
|
|
38868
|
-
case "delete-shared-variables":
|
|
38869
|
-
return `delete-shared-variables (${change.variableNames.length} vars)`;
|
|
38870
|
-
case "create-domain":
|
|
38871
|
-
return `create-domain: ${change.serviceName} → ${change.domain}`;
|
|
38872
|
-
case "delete-domain":
|
|
38873
|
-
return `delete-domain: ${change.serviceName} → ${change.domain}`;
|
|
38919
|
+
return {
|
|
38920
|
+
category: "Services",
|
|
38921
|
+
action: "delete",
|
|
38922
|
+
summary: `${change.name} (${change.serviceId})`
|
|
38923
|
+
};
|
|
38874
38924
|
case "update-service-settings":
|
|
38875
|
-
return
|
|
38876
|
-
|
|
38877
|
-
|
|
38878
|
-
|
|
38879
|
-
|
|
38925
|
+
return {
|
|
38926
|
+
category: "Service settings",
|
|
38927
|
+
action: "update",
|
|
38928
|
+
summary: `${change.serviceName}: ${Object.keys(change.settings).join(", ")}`
|
|
38929
|
+
};
|
|
38880
38930
|
case "update-deployment-trigger": {
|
|
38881
38931
|
const parts = [];
|
|
38882
38932
|
if (change.branch)
|
|
38883
|
-
parts.push(`branch
|
|
38933
|
+
parts.push(`branch → ${change.branch}`);
|
|
38884
38934
|
if (change.checkSuites !== undefined)
|
|
38885
|
-
parts.push(`checkSuites
|
|
38886
|
-
return
|
|
38935
|
+
parts.push(`checkSuites → ${change.checkSuites}`);
|
|
38936
|
+
return {
|
|
38937
|
+
category: "Deployment triggers",
|
|
38938
|
+
action: "update",
|
|
38939
|
+
summary: `${change.serviceName}: ${parts.join(", ")}`
|
|
38940
|
+
};
|
|
38941
|
+
}
|
|
38942
|
+
case "upsert-variables":
|
|
38943
|
+
return {
|
|
38944
|
+
category: "Service variables",
|
|
38945
|
+
action: "update",
|
|
38946
|
+
summary: `${change.serviceName}: set ${Object.keys(change.variables).length} var(s) — ${Object.keys(change.variables).join(", ")}`
|
|
38947
|
+
};
|
|
38948
|
+
case "delete-variables":
|
|
38949
|
+
return {
|
|
38950
|
+
category: "Service variables",
|
|
38951
|
+
action: "delete",
|
|
38952
|
+
summary: `${change.serviceName}: delete ${change.variableNames.length} var(s) — ${change.variableNames.join(", ")}`
|
|
38953
|
+
};
|
|
38954
|
+
case "upsert-shared-variables":
|
|
38955
|
+
return {
|
|
38956
|
+
category: "Shared variables",
|
|
38957
|
+
action: "update",
|
|
38958
|
+
summary: `set ${Object.keys(change.variables).length} var(s) — ${Object.keys(change.variables).join(", ")}`
|
|
38959
|
+
};
|
|
38960
|
+
case "delete-shared-variables":
|
|
38961
|
+
return {
|
|
38962
|
+
category: "Shared variables",
|
|
38963
|
+
action: "delete",
|
|
38964
|
+
summary: `delete ${change.variableNames.length} var(s) — ${change.variableNames.join(", ")}`
|
|
38965
|
+
};
|
|
38966
|
+
case "create-domain": {
|
|
38967
|
+
const port = change.targetPort ? ` (port ${change.targetPort})` : "";
|
|
38968
|
+
return {
|
|
38969
|
+
category: "Domains",
|
|
38970
|
+
action: "create",
|
|
38971
|
+
summary: `${change.serviceName}: ${change.domain}${port}`
|
|
38972
|
+
};
|
|
38973
|
+
}
|
|
38974
|
+
case "delete-domain":
|
|
38975
|
+
return {
|
|
38976
|
+
category: "Domains",
|
|
38977
|
+
action: "delete",
|
|
38978
|
+
summary: `${change.serviceName}: ${change.domain}`
|
|
38979
|
+
};
|
|
38980
|
+
case "create-service-domain": {
|
|
38981
|
+
const port = change.targetPort ? ` (port ${change.targetPort})` : "";
|
|
38982
|
+
return {
|
|
38983
|
+
category: "Railway domains",
|
|
38984
|
+
action: "create",
|
|
38985
|
+
summary: `${change.serviceName}${port}`
|
|
38986
|
+
};
|
|
38887
38987
|
}
|
|
38888
|
-
case "create-service-domain":
|
|
38889
|
-
return `create-service-domain: ${change.serviceName}`;
|
|
38890
38988
|
case "delete-service-domain":
|
|
38891
|
-
return
|
|
38989
|
+
return { category: "Railway domains", action: "delete", summary: change.serviceName };
|
|
38990
|
+
case "create-volume":
|
|
38991
|
+
return {
|
|
38992
|
+
category: "Volumes",
|
|
38993
|
+
action: "create",
|
|
38994
|
+
summary: `${change.serviceName}: ${change.mount}`
|
|
38995
|
+
};
|
|
38996
|
+
case "delete-volume":
|
|
38997
|
+
return {
|
|
38998
|
+
category: "Volumes",
|
|
38999
|
+
action: "delete",
|
|
39000
|
+
summary: `${change.serviceName} (${change.volumeId})`
|
|
39001
|
+
};
|
|
38892
39002
|
case "create-tcp-proxy":
|
|
38893
|
-
return
|
|
39003
|
+
return {
|
|
39004
|
+
category: "TCP proxies",
|
|
39005
|
+
action: "create",
|
|
39006
|
+
summary: `${change.serviceName}: port ${change.applicationPort}`
|
|
39007
|
+
};
|
|
38894
39008
|
case "delete-tcp-proxy":
|
|
38895
|
-
return
|
|
38896
|
-
|
|
38897
|
-
|
|
39009
|
+
return {
|
|
39010
|
+
category: "TCP proxies",
|
|
39011
|
+
action: "delete",
|
|
39012
|
+
summary: `${change.serviceName}: proxy ${change.proxyId}`
|
|
39013
|
+
};
|
|
39014
|
+
case "update-service-limits": {
|
|
39015
|
+
const parts = [];
|
|
39016
|
+
if (change.limits.memoryGB !== undefined)
|
|
39017
|
+
parts.push(`memory: ${change.limits.memoryGB ?? "unset"}GB`);
|
|
39018
|
+
if (change.limits.vCPUs !== undefined)
|
|
39019
|
+
parts.push(`vCPUs: ${change.limits.vCPUs ?? "unset"}`);
|
|
39020
|
+
return {
|
|
39021
|
+
category: "Resource limits",
|
|
39022
|
+
action: "update",
|
|
39023
|
+
summary: `${change.serviceName}: ${parts.join(", ")}`
|
|
39024
|
+
};
|
|
39025
|
+
}
|
|
38898
39026
|
case "enable-static-ips":
|
|
38899
|
-
return
|
|
39027
|
+
return {
|
|
39028
|
+
category: "Static outbound IPs",
|
|
39029
|
+
action: "create",
|
|
39030
|
+
summary: `${change.serviceName}: enable`
|
|
39031
|
+
};
|
|
38900
39032
|
case "disable-static-ips":
|
|
38901
|
-
return
|
|
39033
|
+
return {
|
|
39034
|
+
category: "Static outbound IPs",
|
|
39035
|
+
action: "delete",
|
|
39036
|
+
summary: `${change.serviceName}: disable`
|
|
39037
|
+
};
|
|
38902
39038
|
case "create-bucket":
|
|
38903
|
-
return
|
|
39039
|
+
return { category: "Buckets", action: "create", summary: change.bucketName };
|
|
38904
39040
|
case "delete-bucket":
|
|
38905
|
-
return
|
|
39041
|
+
return { category: "Buckets", action: "delete", summary: change.name };
|
|
38906
39042
|
default: {
|
|
38907
39043
|
const _exhaustive = change;
|
|
38908
|
-
return
|
|
39044
|
+
return { category: "Unknown", action: "update", summary: _exhaustive.type };
|
|
38909
39045
|
}
|
|
38910
39046
|
}
|
|
38911
39047
|
}
|
|
39048
|
+
function changeLabel(change) {
|
|
39049
|
+
const desc = describeChange(change);
|
|
39050
|
+
return `${change.type}: ${desc.summary}`;
|
|
39051
|
+
}
|
|
39052
|
+
var ACTION_ICON = {
|
|
39053
|
+
create: (nc) => green("+", nc),
|
|
39054
|
+
update: (nc) => yellow("~", nc),
|
|
39055
|
+
delete: (nc) => red("-", nc)
|
|
39056
|
+
};
|
|
38912
39057
|
function printChangeset(changeset, options) {
|
|
38913
39058
|
const noColor = options?.noColor ?? false;
|
|
38914
39059
|
const verbose = options?.verbose ?? false;
|
|
@@ -38921,214 +39066,65 @@ ${green("No changes needed", noColor)} — Railway matches desired state.
|
|
|
38921
39066
|
console.log(`
|
|
38922
39067
|
Changeset (${changeset.changes.length} changes):
|
|
38923
39068
|
`);
|
|
38924
|
-
const
|
|
38925
|
-
const
|
|
38926
|
-
|
|
38927
|
-
|
|
38928
|
-
|
|
38929
|
-
|
|
38930
|
-
|
|
38931
|
-
|
|
38932
|
-
|
|
38933
|
-
|
|
38934
|
-
|
|
38935
|
-
|
|
38936
|
-
|
|
38937
|
-
|
|
38938
|
-
|
|
38939
|
-
|
|
38940
|
-
|
|
38941
|
-
|
|
38942
|
-
|
|
38943
|
-
|
|
38944
|
-
|
|
38945
|
-
|
|
38946
|
-
|
|
38947
|
-
|
|
38948
|
-
|
|
38949
|
-
|
|
38950
|
-
|
|
38951
|
-
|
|
38952
|
-
|
|
38953
|
-
|
|
38954
|
-
|
|
38955
|
-
|
|
38956
|
-
}
|
|
38957
|
-
|
|
38958
|
-
|
|
38959
|
-
|
|
38960
|
-
|
|
38961
|
-
|
|
38962
|
-
|
|
38963
|
-
if (c.type === "update-service-settings") {
|
|
38964
|
-
const keys = Object.keys(c.settings).join(", ");
|
|
38965
|
-
console.log(` ${yellow("~", noColor)} ${c.serviceName}: ${keys}`);
|
|
38966
|
-
if (verbose) {
|
|
38967
|
-
for (const [key, value] of Object.entries(c.settings)) {
|
|
38968
|
-
const currentSvc = options?.currentState?.services[c.serviceName];
|
|
38969
|
-
const oldVal = currentSvc ? currentSvc[key] : undefined;
|
|
38970
|
-
const oldStr = oldVal !== undefined ? JSON.stringify(oldVal) : "(unset)";
|
|
38971
|
-
const newStr = value === null ? "(unset)" : JSON.stringify(value);
|
|
38972
|
-
console.log(` ${key}: ${oldStr} → ${newStr}`);
|
|
38973
|
-
}
|
|
38974
|
-
}
|
|
38975
|
-
}
|
|
38976
|
-
}
|
|
38977
|
-
console.log();
|
|
38978
|
-
}
|
|
38979
|
-
if (triggerChanges.length > 0) {
|
|
38980
|
-
console.log(` ${yellow("~", noColor)} DEPLOYMENT TRIGGERS:`);
|
|
38981
|
-
for (const c of triggerChanges) {
|
|
38982
|
-
if (c.type === "update-deployment-trigger") {
|
|
38983
|
-
const parts2 = [];
|
|
38984
|
-
if (c.branch)
|
|
38985
|
-
parts2.push(`branch → ${c.branch}`);
|
|
38986
|
-
if (c.checkSuites !== undefined)
|
|
38987
|
-
parts2.push(`checkSuites → ${c.checkSuites}`);
|
|
38988
|
-
console.log(` ${yellow("~", noColor)} ${c.serviceName}: ${parts2.join(", ")}`);
|
|
38989
|
-
}
|
|
38990
|
-
}
|
|
38991
|
-
console.log();
|
|
38992
|
-
}
|
|
38993
|
-
if (sharedUpsert.length > 0 || sharedDelete.length > 0) {
|
|
38994
|
-
console.log(` ${yellow("~", noColor)} SHARED variables:`);
|
|
38995
|
-
for (const c of sharedUpsert) {
|
|
38996
|
-
if (c.type === "upsert-shared-variables") {
|
|
38997
|
-
for (const [key, value] of Object.entries(c.variables)) {
|
|
38998
|
-
if (verbose) {
|
|
38999
|
-
const oldVal = options?.currentState?.sharedVariables[key];
|
|
39000
|
-
const oldStr = oldVal !== undefined ? maskValue(key, oldVal) : "(unset)";
|
|
39001
|
-
console.log(` ${green("+", noColor)} ${key}: ${dim(`"${oldStr}"`, noColor)} → ${dim(`"${maskValue(key, value)}"`, noColor)}`);
|
|
39002
|
-
} else {
|
|
39003
|
-
console.log(` ${green("+", noColor)} ${key}`);
|
|
39004
|
-
}
|
|
39069
|
+
const groups = new Map;
|
|
39070
|
+
for (const change of changeset.changes) {
|
|
39071
|
+
const desc = describeChange(change);
|
|
39072
|
+
let group = groups.get(desc.category);
|
|
39073
|
+
if (!group) {
|
|
39074
|
+
group = [];
|
|
39075
|
+
groups.set(desc.category, group);
|
|
39076
|
+
}
|
|
39077
|
+
group.push({ change, desc });
|
|
39078
|
+
}
|
|
39079
|
+
for (const [category, entries] of groups) {
|
|
39080
|
+
const actions = new Set(entries.map((e) => e.desc.action));
|
|
39081
|
+
const headerAction = actions.size === 1 ? [...actions][0] : "update";
|
|
39082
|
+
const headerIcon = ACTION_ICON[headerAction](noColor);
|
|
39083
|
+
console.log(` ${headerIcon} ${category.toUpperCase()}:`);
|
|
39084
|
+
for (const { change, desc } of entries) {
|
|
39085
|
+
const icon = ACTION_ICON[desc.action](noColor);
|
|
39086
|
+
if (verbose && change.type === "update-service-settings") {
|
|
39087
|
+
console.log(` ${icon} ${change.serviceName}:`);
|
|
39088
|
+
for (const [key, value] of Object.entries(change.settings)) {
|
|
39089
|
+
const currentSvc = options?.currentState?.services[change.serviceName];
|
|
39090
|
+
const oldVal = currentSvc ? currentSvc[key] : undefined;
|
|
39091
|
+
const oldStr = oldVal !== undefined ? JSON.stringify(oldVal) : "(unset)";
|
|
39092
|
+
const newStr = value === null ? "(unset)" : JSON.stringify(value);
|
|
39093
|
+
console.log(` ${key}: ${oldStr} → ${newStr}`);
|
|
39094
|
+
}
|
|
39095
|
+
} else if (verbose && change.type === "upsert-variables") {
|
|
39096
|
+
console.log(` ${change.serviceName}:`);
|
|
39097
|
+
for (const [key, value] of Object.entries(change.variables)) {
|
|
39098
|
+
const currentSvc = options?.currentState?.services[change.serviceName];
|
|
39099
|
+
const oldVal = currentSvc?.variables[key];
|
|
39100
|
+
const oldStr = oldVal !== undefined ? maskValue(key, oldVal) : "(unset)";
|
|
39101
|
+
console.log(` ${icon} ${key}: ${dim(`"${oldStr}"`, noColor)} → ${dim(`"${maskValue(key, value)}"`, noColor)}`);
|
|
39102
|
+
}
|
|
39103
|
+
} else if (verbose && change.type === "upsert-shared-variables") {
|
|
39104
|
+
for (const [key, value] of Object.entries(change.variables)) {
|
|
39105
|
+
const oldVal = options?.currentState?.sharedVariables[key];
|
|
39106
|
+
const oldStr = oldVal !== undefined ? maskValue(key, oldVal) : "(unset)";
|
|
39107
|
+
console.log(` ${icon} ${key}: ${dim(`"${oldStr}"`, noColor)} → ${dim(`"${maskValue(key, value)}"`, noColor)}`);
|
|
39005
39108
|
}
|
|
39006
|
-
}
|
|
39007
|
-
}
|
|
39008
|
-
for (const c of sharedDelete) {
|
|
39009
|
-
if (c.type === "delete-shared-variables") {
|
|
39010
|
-
for (const name of c.variableNames) {
|
|
39011
|
-
console.log(` ${red("-", noColor)} ${name}`);
|
|
39012
|
-
}
|
|
39013
|
-
}
|
|
39014
|
-
}
|
|
39015
|
-
console.log();
|
|
39016
|
-
}
|
|
39017
|
-
if (upsertVars.length > 0 || deleteVars.length > 0) {
|
|
39018
|
-
console.log(` ${yellow("~", noColor)} SERVICE variables:`);
|
|
39019
|
-
for (const c of upsertVars) {
|
|
39020
|
-
if (c.type === "upsert-variables") {
|
|
39021
|
-
const keys = Object.keys(c.variables);
|
|
39022
|
-
if (verbose) {
|
|
39023
|
-
console.log(` ${c.serviceName}:`);
|
|
39024
|
-
for (const [key, value] of Object.entries(c.variables)) {
|
|
39025
|
-
const currentSvc = options?.currentState?.services[c.serviceName];
|
|
39026
|
-
const oldVal = currentSvc?.variables[key];
|
|
39027
|
-
const oldStr = oldVal !== undefined ? maskValue(key, oldVal) : "(unset)";
|
|
39028
|
-
console.log(` ${green("+", noColor)} ${key}: ${dim(`"${oldStr}"`, noColor)} → ${dim(`"${maskValue(key, value)}"`, noColor)}`);
|
|
39029
|
-
}
|
|
39030
|
-
} else {
|
|
39031
|
-
console.log(` ${c.serviceName}: set ${keys.length} var(s) — ${keys.join(", ")}`);
|
|
39032
|
-
}
|
|
39033
|
-
}
|
|
39034
|
-
}
|
|
39035
|
-
for (const c of deleteVars) {
|
|
39036
|
-
if (c.type === "delete-variables") {
|
|
39037
|
-
console.log(` ${c.serviceName}: ${red("delete", noColor)} ${c.variableNames.length} var(s) — ${c.variableNames.join(", ")}`);
|
|
39038
|
-
}
|
|
39039
|
-
}
|
|
39040
|
-
console.log();
|
|
39041
|
-
}
|
|
39042
|
-
if (domainChanges.length > 0) {
|
|
39043
|
-
console.log(` ${yellow("~", noColor)} DOMAINS:`);
|
|
39044
|
-
for (const c of domainChanges) {
|
|
39045
|
-
if (c.type === "create-domain") {
|
|
39046
|
-
console.log(` ${green("+", noColor)} ${c.serviceName}: ${c.domain}`);
|
|
39047
|
-
} else if (c.type === "delete-domain") {
|
|
39048
|
-
console.log(` ${red("-", noColor)} ${c.serviceName}: ${c.domain}`);
|
|
39049
|
-
}
|
|
39050
|
-
}
|
|
39051
|
-
console.log();
|
|
39052
|
-
}
|
|
39053
|
-
if (volumeCreates.length > 0 || volumeDeletes.length > 0) {
|
|
39054
|
-
console.log(` ${yellow("~", noColor)} VOLUMES:`);
|
|
39055
|
-
for (const c of volumeCreates) {
|
|
39056
|
-
if (c.type === "create-volume") {
|
|
39057
|
-
console.log(` ${green("+", noColor)} ${c.serviceName}: ${c.mount}`);
|
|
39058
|
-
}
|
|
39059
|
-
}
|
|
39060
|
-
for (const c of volumeDeletes) {
|
|
39061
|
-
if (c.type === "delete-volume") {
|
|
39062
|
-
console.log(` ${red("-", noColor)} ${c.serviceName}`);
|
|
39063
|
-
}
|
|
39064
|
-
}
|
|
39065
|
-
console.log();
|
|
39066
|
-
}
|
|
39067
|
-
if (serviceDomainChanges.length > 0) {
|
|
39068
|
-
console.log(` ${yellow("~", noColor)} RAILWAY DOMAINS:`);
|
|
39069
|
-
for (const c of serviceDomainChanges) {
|
|
39070
|
-
if (c.type === "create-service-domain") {
|
|
39071
|
-
const port = c.targetPort ? ` (port ${c.targetPort})` : "";
|
|
39072
|
-
console.log(` ${green("+", noColor)} ${c.serviceName}${port}`);
|
|
39073
|
-
} else if (c.type === "delete-service-domain") {
|
|
39074
|
-
console.log(` ${red("-", noColor)} ${c.serviceName}`);
|
|
39075
|
-
}
|
|
39076
|
-
}
|
|
39077
|
-
console.log();
|
|
39078
|
-
}
|
|
39079
|
-
if (tcpProxyChanges.length > 0) {
|
|
39080
|
-
console.log(` ${yellow("~", noColor)} TCP PROXIES:`);
|
|
39081
|
-
for (const c of tcpProxyChanges) {
|
|
39082
|
-
if (c.type === "create-tcp-proxy") {
|
|
39083
|
-
console.log(` ${green("+", noColor)} ${c.serviceName}: port ${c.applicationPort}`);
|
|
39084
|
-
} else if (c.type === "delete-tcp-proxy") {
|
|
39085
|
-
console.log(` ${red("-", noColor)} ${c.serviceName}`);
|
|
39086
|
-
}
|
|
39087
|
-
}
|
|
39088
|
-
console.log();
|
|
39089
|
-
}
|
|
39090
|
-
if (limitsChanges.length > 0) {
|
|
39091
|
-
console.log(` ${yellow("~", noColor)} RESOURCE LIMITS:`);
|
|
39092
|
-
for (const c of limitsChanges) {
|
|
39093
|
-
if (c.type === "update-service-limits") {
|
|
39094
|
-
const parts2 = [];
|
|
39095
|
-
if (c.limits.memoryGB !== undefined)
|
|
39096
|
-
parts2.push(`memory: ${c.limits.memoryGB ?? "unset"}GB`);
|
|
39097
|
-
if (c.limits.vCPUs !== undefined)
|
|
39098
|
-
parts2.push(`vCPUs: ${c.limits.vCPUs ?? "unset"}`);
|
|
39099
|
-
console.log(` ${yellow("~", noColor)} ${c.serviceName}: ${parts2.join(", ")}`);
|
|
39100
|
-
}
|
|
39101
|
-
}
|
|
39102
|
-
console.log();
|
|
39103
|
-
}
|
|
39104
|
-
if (staticIpChanges.length > 0) {
|
|
39105
|
-
console.log(` ${yellow("~", noColor)} STATIC OUTBOUND IPS:`);
|
|
39106
|
-
for (const c of staticIpChanges) {
|
|
39107
|
-
if (c.type === "enable-static-ips") {
|
|
39108
|
-
console.log(` ${green("+", noColor)} ${c.serviceName}: enable`);
|
|
39109
|
-
} else if (c.type === "disable-static-ips") {
|
|
39110
|
-
console.log(` ${red("-", noColor)} ${c.serviceName}: disable`);
|
|
39109
|
+
} else {
|
|
39110
|
+
console.log(` ${icon} ${desc.summary}`);
|
|
39111
39111
|
}
|
|
39112
39112
|
}
|
|
39113
39113
|
console.log();
|
|
39114
39114
|
}
|
|
39115
|
-
|
|
39116
|
-
|
|
39117
|
-
|
|
39118
|
-
|
|
39119
|
-
|
|
39120
|
-
|
|
39121
|
-
|
|
39122
|
-
|
|
39123
|
-
|
|
39124
|
-
|
|
39125
|
-
|
|
39115
|
+
let createCount = 0;
|
|
39116
|
+
let updateCount = 0;
|
|
39117
|
+
let deleteCount = 0;
|
|
39118
|
+
for (const entries of groups.values()) {
|
|
39119
|
+
for (const { desc } of entries) {
|
|
39120
|
+
if (desc.action === "create")
|
|
39121
|
+
createCount++;
|
|
39122
|
+
else if (desc.action === "update")
|
|
39123
|
+
updateCount++;
|
|
39124
|
+
else
|
|
39125
|
+
deleteCount++;
|
|
39126
39126
|
}
|
|
39127
|
-
console.log();
|
|
39128
39127
|
}
|
|
39129
|
-
const createCount = creates.length + volumeCreates.length + bucketCreates.length + serviceDomainChanges.filter((c) => c.type === "create-service-domain").length + tcpProxyChanges.filter((c) => c.type === "create-tcp-proxy").length + staticIpChanges.filter((c) => c.type === "enable-static-ips").length;
|
|
39130
|
-
const updateCount = settingsChanges.length + triggerChanges.length + limitsChanges.length + upsertVars.length + sharedUpsert.length + domainChanges.filter((c) => c.type === "create-domain").length;
|
|
39131
|
-
const deleteCount = deletes.length + deleteVars.length + sharedDelete.length + volumeDeletes.length + bucketDeletes.length + domainChanges.filter((c) => c.type === "delete-domain").length + serviceDomainChanges.filter((c) => c.type === "delete-service-domain").length + tcpProxyChanges.filter((c) => c.type === "delete-tcp-proxy").length + staticIpChanges.filter((c) => c.type === "disable-static-ips").length;
|
|
39132
39128
|
const parts = [];
|
|
39133
39129
|
if (createCount > 0)
|
|
39134
39130
|
parts.push(green(`${createCount} to create`, noColor));
|
|
@@ -39381,8 +39377,9 @@ async function applyChange(client, change, projectId, environmentId, createdServ
|
|
|
39381
39377
|
}
|
|
39382
39378
|
|
|
39383
39379
|
// src/util.ts
|
|
39380
|
+
var import_fast_deep_equal = __toESM(require_fast_deep_equal(), 1);
|
|
39384
39381
|
function deepEqual(a, b) {
|
|
39385
|
-
return
|
|
39382
|
+
return import_fast_deep_equal.default(a, b);
|
|
39386
39383
|
}
|
|
39387
39384
|
|
|
39388
39385
|
// src/reconcile/diff.ts
|
|
@@ -39868,7 +39865,7 @@ async function run(configPath, opts) {
|
|
|
39868
39865
|
const raw = readFileSync3(absPath, "utf-8");
|
|
39869
39866
|
const parsed = $parse(raw);
|
|
39870
39867
|
validateEnvironmentConfig(parsed);
|
|
39871
|
-
loadEnvironmentConfig(configPath);
|
|
39868
|
+
loadEnvironmentConfig(configPath, { lenient: true });
|
|
39872
39869
|
console.log("Config is valid.");
|
|
39873
39870
|
process.exit(0);
|
|
39874
39871
|
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tachyon-gg/railway-deploy",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "https://github.com/tachyon-gg/railway-deploy"
|
|
7
|
+
"url": "git+https://github.com/tachyon-gg/railway-deploy.git"
|
|
8
8
|
},
|
|
9
9
|
"main": "./dist/index.js",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": "./dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"bin": {
|
|
14
|
-
"railway-deploy": "
|
|
14
|
+
"railway-deploy": "dist/index.js"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"dist/"
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"@graphql-typed-document-node/core": "^3.2.0",
|
|
36
36
|
"commander": "^14.0.3",
|
|
37
37
|
"dotenv": "^17.3.1",
|
|
38
|
+
"fast-deep-equal": "^3.1.3",
|
|
38
39
|
"graphql": "^16.10.0",
|
|
39
40
|
"graphql-request": "^7.1.2",
|
|
40
41
|
"yaml": "^2.7.0",
|