@catladder/cli 0.0.0-next-cb2cfd57 → 0.0.0-next-c392e917

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.
@@ -9632,9 +9632,14 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
9632
9632
  // generation time. For review envs the service name part still
9633
9633
  // contains a runtime expression (the review slug), so the host stays
9634
9634
  // a bash expression there; the suffix is always a literal.
9635
+ //
9636
+ // The service name has to come from getRawServiceNameForEnvContext,
9637
+ // not from fullName: it is shortened when the label would otherwise
9638
+ // exceed what cloud run serves deterministically, and the url must
9639
+ // name the service that is actually deployed.
9635
9640
  const HOSTNAME_INTERNAL = deployConfigRaw && envType !== "local"
9636
9641
  ? (0, bash_1.joinBashExpressions)([
9637
- fullName,
9642
+ (0, getServiceName_1.getRawServiceNameForEnvContext)(ctx),
9638
9643
  `${(0, store_1.getGcloudProjectNumber)(fullConfig, deployConfigRaw.projectId)}.${deployConfigRaw.region}.run.app`,
9639
9644
  ], "-").toLowerCase()
9640
9645
  : undefined;
@@ -9896,16 +9901,197 @@ exports.getCloudRunServiceOrJobArgsArg = getCloudRunServiceOrJobArgsArg;
9896
9901
  /***/ }),
9897
9902
 
9898
9903
  /***/ 33102:
9899
- /***/ ((__unused_webpack_module, exports) => {
9904
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
9900
9905
 
9901
9906
  "use strict";
9902
9907
 
9903
9908
  Object.defineProperty(exports, "__esModule", ({ value: true }));
9904
- exports.getServiceNameForEnvContext = exports.getServiceName = void 0;
9905
- const getServiceName = (context) => context.environment.fullName.toLowerCase();
9909
+ exports.getRawServiceNameForEnvContext = exports.getServiceNameForEnvContext = exports.getServiceName = exports.resolveCloudRunComponentPart = exports.REVIEW_SLUG_LENGTH_BUDGET = exports.CLOUD_RUN_DNS_SEGMENT_LIMIT = void 0;
9910
+ const bash_1 = __nccwpck_require__(94143);
9911
+ const store_1 = __nccwpck_require__(2789);
9912
+ /**
9913
+ * cloud run only serves its deterministic url
9914
+ * `https://<service>-<projectNumber>.<region>.run.app` while that first dns
9915
+ * label stays within the 63 characters a dns label allows — the label holds
9916
+ * the service name, the project number and any traffic tag together.
9917
+ *
9918
+ * Beyond it cloud run silently switches to a legacy url built from a random
9919
+ * identifier that nothing can recompute. The url catladder generates would
9920
+ * then be a hostname that can never resolve, and everything consuming
9921
+ * ROOT_URL/ROOT_URL_INTERNAL (cloud tasks targets, service-to-service
9922
+ * calls) fails with a dns error instead of a helpful one — which is why the
9923
+ * component part is shortened to stay under the limit rather than left to
9924
+ * overflow.
9925
+ *
9926
+ * https://cloud.google.com/run/docs/triggering/https-request
9927
+ */
9928
+ exports.CLOUD_RUN_DNS_SEGMENT_LIMIT = 63;
9929
+ /**
9930
+ * review environments resolve their slug at runtime (`mr<iid>` on gitlab,
9931
+ * `pr<number>` on github), so its exact length is unknown while generating.
9932
+ * Budget for a six digit number so that service names — and with them the
9933
+ * urls of already deployed services — do not start changing years later
9934
+ * just because a project's merge request numbers grew a digit.
9935
+ */
9936
+ exports.REVIEW_SLUG_LENGTH_BUDGET = "mr123456".length;
9937
+ /**
9938
+ * a service name shortened past this point is no longer recognizable. When
9939
+ * even this does not fit, the fixed parts (customer name, app name, env,
9940
+ * project number) are what needs to shrink — only the user can do that.
9941
+ */
9942
+ const MIN_COMPONENT_PART_LENGTH = 6;
9943
+ const quote = (name) => `"${name}"`;
9944
+ /**
9945
+ * a trailing dash would end up in the hostname as `...-foo-.run.app`
9946
+ */
9947
+ const shortenTo = (name, maxLength) => name.slice(0, maxLength).replace(/-+$/, "");
9948
+ /**
9949
+ * the component-name part of a cloud run service name, shortened just
9950
+ * enough to keep the deterministic url resolvable.
9951
+ *
9952
+ * Only the component part is shortened: the env and review slug parts have
9953
+ * to stay intact (they are what makes the name unique per environment), the
9954
+ * project number is fixed, and customerName/appName are shared by every
9955
+ * service of the project.
9956
+ */
9957
+ const resolveCloudRunComponentPart = ({ customerName, appName, env, isReviewEnv, componentName, projectNumber, otherComponentNames, }) => {
9958
+ const fixedParts = [
9959
+ customerName,
9960
+ appName,
9961
+ env,
9962
+ ...(isReviewEnv ? ["_".repeat(exports.REVIEW_SLUG_LENGTH_BUDGET)] : []),
9963
+ projectNumber,
9964
+ ];
9965
+ // + 1 for the dash that joins the component part to the rest
9966
+ const fixedLength = fixedParts.join("-").length + 1;
9967
+ const available = exports.CLOUD_RUN_DNS_SEGMENT_LIMIT - fixedLength;
9968
+ if (componentName.length <= available) {
9969
+ return {
9970
+ value: componentName,
9971
+ dropped: 0,
9972
+ dnsSegmentLength: fixedLength + componentName.length,
9973
+ };
9974
+ }
9975
+ if (available < MIN_COMPONENT_PART_LENGTH) {
9976
+ throw new Error(`Cannot build a resolvable cloud run url for component ${quote(componentName)} in env ${quote(env)}.\n` +
9977
+ `Everything but the component name already takes ${fixedLength} of the ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters ` +
9978
+ `a dns label allows (${fixedParts.join("-")}-<component>), leaving only ${available} for the component name.\n` +
9979
+ `Shorten appName (${quote(appName)}) or customerName (${quote(customerName)}) by at least ` +
9980
+ `${MIN_COMPONENT_PART_LENGTH - available} character(s).` +
9981
+ (isReviewEnv
9982
+ ? `\nReview environments also carry a runtime slug, for which ${exports.REVIEW_SLUG_LENGTH_BUDGET} characters are reserved.`
9983
+ : ""));
9984
+ }
9985
+ const value = shortenTo(componentName, available);
9986
+ const colliding = otherComponentNames.filter((other) => shortenTo(other, available) === value);
9987
+ if (colliding.length > 0) {
9988
+ throw new Error(`Cloud run service names collide in env ${quote(env)}: ${quote(componentName)} and ` +
9989
+ `${colliding.map(quote).join(", ")} all shorten to ${quote(value)}, so they would deploy over each other.\n` +
9990
+ `The deterministic cloud run url allows ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters, which leaves ${available} ` +
9991
+ `for the component name here — rename the components so their first ${available} characters differ.`);
9992
+ }
9993
+ return {
9994
+ value,
9995
+ dropped: componentName.length - value.length,
9996
+ dnsSegmentLength: fixedLength + value.length,
9997
+ };
9998
+ };
9999
+ exports.resolveCloudRunComponentPart = resolveCloudRunComponentPart;
10000
+ /**
10001
+ * one note per shortened service name instead of one per generated job:
10002
+ * service names are resolved again for every job that references them
10003
+ */
10004
+ const reportedTruncations = new Set();
10005
+ const reportTruncation = (env, componentName, { value, dnsSegmentLength }) => {
10006
+ const key = `${env}/${componentName}`;
10007
+ if (reportedTruncations.has(key)) {
10008
+ return;
10009
+ }
10010
+ reportedTruncations.add(key);
10011
+ console.warn(`ℹ️ component "${componentName}" deploys to cloud run as "...-${value}" in env "${env}": ` +
10012
+ `the full name would push the url past the ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters cloud run ` +
10013
+ `serves deterministically, so the component part is shortened ` +
10014
+ `(${dnsSegmentLength} of ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters used).`);
10015
+ };
10016
+ /**
10017
+ * the cloud run service name before lowercasing, so that callers keep
10018
+ * lowercasing the whole expression exactly like they did before.
10019
+ *
10020
+ * Returns `fullName` unchanged unless the component part had to be
10021
+ * shortened — every project whose url already fits generates byte-identical
10022
+ * output.
10023
+ *
10024
+ * Note that the composition below has to match the one `fullName` is built
10025
+ * from in getEnvironmentContext; the tests pin that they agree.
10026
+ */
10027
+ const getRawServiceName = ({ fullName, environmentSlugPrefix, componentName, env, isReviewEnv, deployConfig, config, }) => {
10028
+ const projectNumber = deployConfig
10029
+ ? (0, store_1.readGcloudProjectNumber)(config, deployConfig.projectId)
10030
+ : null;
10031
+ if (!projectNumber) {
10032
+ // without the project number there is no deterministic url to keep
10033
+ // resolvable — generating the url itself fails with a store error that
10034
+ // says how to fix it, so don't second-guess the name here
10035
+ return fullName;
10036
+ }
10037
+ const componentPart = (0, exports.resolveCloudRunComponentPart)({
10038
+ customerName: config.customerName,
10039
+ appName: config.appName,
10040
+ env,
10041
+ isReviewEnv,
10042
+ componentName,
10043
+ projectNumber,
10044
+ otherComponentNames: Object.keys(config.components).filter((name) => name !== componentName),
10045
+ });
10046
+ if (componentPart.dropped === 0) {
10047
+ return fullName;
10048
+ }
10049
+ reportTruncation(env, componentName, componentPart);
10050
+ return (0, bash_1.joinBashExpressions)([
10051
+ config.customerName,
10052
+ config.appName,
10053
+ environmentSlugPrefix,
10054
+ componentPart.value,
10055
+ ], "-");
10056
+ };
10057
+ const fromComponentContext = (context) => {
10058
+ var _a;
10059
+ const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
10060
+ return {
10061
+ fullName: context.environment.fullName,
10062
+ environmentSlugPrefix: context.environment.slugPrefix,
10063
+ componentName: context.name,
10064
+ env: context.env,
10065
+ isReviewEnv: context.environment.envType === "review",
10066
+ deployConfig: deployConfig && deployConfig.type === "google-cloudrun"
10067
+ ? deployConfig
10068
+ : null,
10069
+ config: context.fullConfig,
10070
+ };
10071
+ };
10072
+ const fromEnvironmentContext = (context) => ({
10073
+ fullName: context.fullName,
10074
+ environmentSlugPrefix: context.environmentSlugPrefix,
10075
+ componentName: context.componentName,
10076
+ env: context.env,
10077
+ isReviewEnv: context.envType === "review",
10078
+ deployConfig: context.deployConfigRaw || null,
10079
+ config: context.fullConfig,
10080
+ });
10081
+ /**
10082
+ * the cloud run service name as it is passed to `gcloud run` — lowercased,
10083
+ * and shortened when the deterministic url would otherwise not fit.
10084
+ */
10085
+ const getServiceName = (context) => getRawServiceName(fromComponentContext(context)).toLowerCase();
9906
10086
  exports.getServiceName = getServiceName;
9907
- const getServiceNameForEnvContext = (context) => context.fullName.toLowerCase();
10087
+ const getServiceNameForEnvContext = (context) => getRawServiceName(fromEnvironmentContext(context)).toLowerCase();
9908
10088
  exports.getServiceNameForEnvContext = getServiceNameForEnvContext;
10089
+ /**
10090
+ * the service name part of the deterministic url, still to be lowercased
10091
+ * together with the rest of the hostname by the caller.
10092
+ */
10093
+ const getRawServiceNameForEnvContext = (context) => getRawServiceName(fromEnvironmentContext(context));
10094
+ exports.getRawServiceNameForEnvContext = getRawServiceNameForEnvContext;
9909
10095
  //# sourceMappingURL=getServiceName.js.map
9910
10096
 
9911
10097
  /***/ }),
@@ -12322,7 +12508,7 @@ exports.getRunnerImage = getRunnerImage;
12322
12508
  "use strict";
12323
12509
 
12324
12510
  Object.defineProperty(exports, "__esModule", ({ value: true }));
12325
- exports.getGcloudProjectNumber = exports.readCatladderStore = exports.getCatladderStorePath = exports.catladderStoreSchema = exports.CATLADDER_STORE_FILE = exports.CATLADDER_STORE_FILE_NAME = exports.CATLADDER_STORE_DIR = void 0;
12511
+ exports.getGcloudProjectNumber = exports.readGcloudProjectNumber = exports.readCatladderStore = exports.getCatladderStorePath = exports.catladderStoreSchema = exports.CATLADDER_STORE_FILE = exports.CATLADDER_STORE_FILE_NAME = exports.CATLADDER_STORE_DIR = void 0;
12326
12512
  const fs_1 = __nccwpck_require__(79896);
12327
12513
  const path_1 = __nccwpck_require__(16928);
12328
12514
  const yaml_1 = __nccwpck_require__(99292);
@@ -12374,6 +12560,13 @@ const readCatladderStore = (directory = process.cwd()) => {
12374
12560
  }
12375
12561
  };
12376
12562
  exports.readCatladderStore = readCatladderStore;
12563
+ /**
12564
+ * gcloud project number from the store, or null when it has not been
12565
+ * fetched yet. Use this where a missing number is not itself the problem —
12566
+ * `getGcloudProjectNumber` is the one that reports it.
12567
+ */
12568
+ const readGcloudProjectNumber = (config, projectId) => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.store) === null || _a === void 0 ? void 0 : _a.gcloudProjects) === null || _b === void 0 ? void 0 : _b[projectId]) === null || _c === void 0 ? void 0 : _c.projectNumber) !== null && _d !== void 0 ? _d : null; };
12569
+ exports.readGcloudProjectNumber = readGcloudProjectNumber;
12377
12570
  /**
12378
12571
  * gcloud project number from the store — needed to compute deterministic
12379
12572
  * cloud run urls (`<service>-<projectNumber>.<region>.run.app`) at
@@ -12383,8 +12576,7 @@ exports.readCatladderStore = readCatladderStore;
12383
12576
  * catenv fail until `catladder project setup` has stored it.
12384
12577
  */
12385
12578
  const getGcloudProjectNumber = (config, projectId) => {
12386
- var _a, _b, _c;
12387
- const projectNumber = (_c = (_b = (_a = config.store) === null || _a === void 0 ? void 0 : _a.gcloudProjects) === null || _b === void 0 ? void 0 : _b[projectId]) === null || _c === void 0 ? void 0 : _c.projectNumber;
12579
+ const projectNumber = (0, exports.readGcloudProjectNumber)(config, projectId);
12388
12580
  if (!projectNumber) {
12389
12581
  throw new Error(`Missing gcloud project number for project "${projectId}" in ${exports.CATLADDER_STORE_FILE}.\n` +
12390
12582
  `Run "catladder project setup" to fetch and store it.`);
@@ -15564,9 +15564,14 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
15564
15564
  // generation time. For review envs the service name part still
15565
15565
  // contains a runtime expression (the review slug), so the host stays
15566
15566
  // a bash expression there; the suffix is always a literal.
15567
+ //
15568
+ // The service name has to come from getRawServiceNameForEnvContext,
15569
+ // not from fullName: it is shortened when the label would otherwise
15570
+ // exceed what cloud run serves deterministically, and the url must
15571
+ // name the service that is actually deployed.
15567
15572
  const HOSTNAME_INTERNAL = deployConfigRaw && envType !== "local"
15568
15573
  ? (0, bash_1.joinBashExpressions)([
15569
- fullName,
15574
+ (0, getServiceName_1.getRawServiceNameForEnvContext)(ctx),
15570
15575
  `${(0, store_1.getGcloudProjectNumber)(fullConfig, deployConfigRaw.projectId)}.${deployConfigRaw.region}.run.app`,
15571
15576
  ], "-").toLowerCase()
15572
15577
  : undefined;
@@ -15828,16 +15833,197 @@ exports.getCloudRunServiceOrJobArgsArg = getCloudRunServiceOrJobArgsArg;
15828
15833
  /***/ }),
15829
15834
 
15830
15835
  /***/ 33102:
15831
- /***/ ((__unused_webpack_module, exports) => {
15836
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
15832
15837
 
15833
15838
  "use strict";
15834
15839
 
15835
15840
  Object.defineProperty(exports, "__esModule", ({ value: true }));
15836
- exports.getServiceNameForEnvContext = exports.getServiceName = void 0;
15837
- const getServiceName = (context) => context.environment.fullName.toLowerCase();
15841
+ exports.getRawServiceNameForEnvContext = exports.getServiceNameForEnvContext = exports.getServiceName = exports.resolveCloudRunComponentPart = exports.REVIEW_SLUG_LENGTH_BUDGET = exports.CLOUD_RUN_DNS_SEGMENT_LIMIT = void 0;
15842
+ const bash_1 = __nccwpck_require__(94143);
15843
+ const store_1 = __nccwpck_require__(2789);
15844
+ /**
15845
+ * cloud run only serves its deterministic url
15846
+ * `https://<service>-<projectNumber>.<region>.run.app` while that first dns
15847
+ * label stays within the 63 characters a dns label allows — the label holds
15848
+ * the service name, the project number and any traffic tag together.
15849
+ *
15850
+ * Beyond it cloud run silently switches to a legacy url built from a random
15851
+ * identifier that nothing can recompute. The url catladder generates would
15852
+ * then be a hostname that can never resolve, and everything consuming
15853
+ * ROOT_URL/ROOT_URL_INTERNAL (cloud tasks targets, service-to-service
15854
+ * calls) fails with a dns error instead of a helpful one — which is why the
15855
+ * component part is shortened to stay under the limit rather than left to
15856
+ * overflow.
15857
+ *
15858
+ * https://cloud.google.com/run/docs/triggering/https-request
15859
+ */
15860
+ exports.CLOUD_RUN_DNS_SEGMENT_LIMIT = 63;
15861
+ /**
15862
+ * review environments resolve their slug at runtime (`mr<iid>` on gitlab,
15863
+ * `pr<number>` on github), so its exact length is unknown while generating.
15864
+ * Budget for a six digit number so that service names — and with them the
15865
+ * urls of already deployed services — do not start changing years later
15866
+ * just because a project's merge request numbers grew a digit.
15867
+ */
15868
+ exports.REVIEW_SLUG_LENGTH_BUDGET = "mr123456".length;
15869
+ /**
15870
+ * a service name shortened past this point is no longer recognizable. When
15871
+ * even this does not fit, the fixed parts (customer name, app name, env,
15872
+ * project number) are what needs to shrink — only the user can do that.
15873
+ */
15874
+ const MIN_COMPONENT_PART_LENGTH = 6;
15875
+ const quote = (name) => `"${name}"`;
15876
+ /**
15877
+ * a trailing dash would end up in the hostname as `...-foo-.run.app`
15878
+ */
15879
+ const shortenTo = (name, maxLength) => name.slice(0, maxLength).replace(/-+$/, "");
15880
+ /**
15881
+ * the component-name part of a cloud run service name, shortened just
15882
+ * enough to keep the deterministic url resolvable.
15883
+ *
15884
+ * Only the component part is shortened: the env and review slug parts have
15885
+ * to stay intact (they are what makes the name unique per environment), the
15886
+ * project number is fixed, and customerName/appName are shared by every
15887
+ * service of the project.
15888
+ */
15889
+ const resolveCloudRunComponentPart = ({ customerName, appName, env, isReviewEnv, componentName, projectNumber, otherComponentNames, }) => {
15890
+ const fixedParts = [
15891
+ customerName,
15892
+ appName,
15893
+ env,
15894
+ ...(isReviewEnv ? ["_".repeat(exports.REVIEW_SLUG_LENGTH_BUDGET)] : []),
15895
+ projectNumber,
15896
+ ];
15897
+ // + 1 for the dash that joins the component part to the rest
15898
+ const fixedLength = fixedParts.join("-").length + 1;
15899
+ const available = exports.CLOUD_RUN_DNS_SEGMENT_LIMIT - fixedLength;
15900
+ if (componentName.length <= available) {
15901
+ return {
15902
+ value: componentName,
15903
+ dropped: 0,
15904
+ dnsSegmentLength: fixedLength + componentName.length,
15905
+ };
15906
+ }
15907
+ if (available < MIN_COMPONENT_PART_LENGTH) {
15908
+ throw new Error(`Cannot build a resolvable cloud run url for component ${quote(componentName)} in env ${quote(env)}.\n` +
15909
+ `Everything but the component name already takes ${fixedLength} of the ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters ` +
15910
+ `a dns label allows (${fixedParts.join("-")}-<component>), leaving only ${available} for the component name.\n` +
15911
+ `Shorten appName (${quote(appName)}) or customerName (${quote(customerName)}) by at least ` +
15912
+ `${MIN_COMPONENT_PART_LENGTH - available} character(s).` +
15913
+ (isReviewEnv
15914
+ ? `\nReview environments also carry a runtime slug, for which ${exports.REVIEW_SLUG_LENGTH_BUDGET} characters are reserved.`
15915
+ : ""));
15916
+ }
15917
+ const value = shortenTo(componentName, available);
15918
+ const colliding = otherComponentNames.filter((other) => shortenTo(other, available) === value);
15919
+ if (colliding.length > 0) {
15920
+ throw new Error(`Cloud run service names collide in env ${quote(env)}: ${quote(componentName)} and ` +
15921
+ `${colliding.map(quote).join(", ")} all shorten to ${quote(value)}, so they would deploy over each other.\n` +
15922
+ `The deterministic cloud run url allows ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters, which leaves ${available} ` +
15923
+ `for the component name here — rename the components so their first ${available} characters differ.`);
15924
+ }
15925
+ return {
15926
+ value,
15927
+ dropped: componentName.length - value.length,
15928
+ dnsSegmentLength: fixedLength + value.length,
15929
+ };
15930
+ };
15931
+ exports.resolveCloudRunComponentPart = resolveCloudRunComponentPart;
15932
+ /**
15933
+ * one note per shortened service name instead of one per generated job:
15934
+ * service names are resolved again for every job that references them
15935
+ */
15936
+ const reportedTruncations = new Set();
15937
+ const reportTruncation = (env, componentName, { value, dnsSegmentLength }) => {
15938
+ const key = `${env}/${componentName}`;
15939
+ if (reportedTruncations.has(key)) {
15940
+ return;
15941
+ }
15942
+ reportedTruncations.add(key);
15943
+ console.warn(`ℹ️ component "${componentName}" deploys to cloud run as "...-${value}" in env "${env}": ` +
15944
+ `the full name would push the url past the ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters cloud run ` +
15945
+ `serves deterministically, so the component part is shortened ` +
15946
+ `(${dnsSegmentLength} of ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters used).`);
15947
+ };
15948
+ /**
15949
+ * the cloud run service name before lowercasing, so that callers keep
15950
+ * lowercasing the whole expression exactly like they did before.
15951
+ *
15952
+ * Returns `fullName` unchanged unless the component part had to be
15953
+ * shortened — every project whose url already fits generates byte-identical
15954
+ * output.
15955
+ *
15956
+ * Note that the composition below has to match the one `fullName` is built
15957
+ * from in getEnvironmentContext; the tests pin that they agree.
15958
+ */
15959
+ const getRawServiceName = ({ fullName, environmentSlugPrefix, componentName, env, isReviewEnv, deployConfig, config, }) => {
15960
+ const projectNumber = deployConfig
15961
+ ? (0, store_1.readGcloudProjectNumber)(config, deployConfig.projectId)
15962
+ : null;
15963
+ if (!projectNumber) {
15964
+ // without the project number there is no deterministic url to keep
15965
+ // resolvable — generating the url itself fails with a store error that
15966
+ // says how to fix it, so don't second-guess the name here
15967
+ return fullName;
15968
+ }
15969
+ const componentPart = (0, exports.resolveCloudRunComponentPart)({
15970
+ customerName: config.customerName,
15971
+ appName: config.appName,
15972
+ env,
15973
+ isReviewEnv,
15974
+ componentName,
15975
+ projectNumber,
15976
+ otherComponentNames: Object.keys(config.components).filter((name) => name !== componentName),
15977
+ });
15978
+ if (componentPart.dropped === 0) {
15979
+ return fullName;
15980
+ }
15981
+ reportTruncation(env, componentName, componentPart);
15982
+ return (0, bash_1.joinBashExpressions)([
15983
+ config.customerName,
15984
+ config.appName,
15985
+ environmentSlugPrefix,
15986
+ componentPart.value,
15987
+ ], "-");
15988
+ };
15989
+ const fromComponentContext = (context) => {
15990
+ var _a;
15991
+ const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
15992
+ return {
15993
+ fullName: context.environment.fullName,
15994
+ environmentSlugPrefix: context.environment.slugPrefix,
15995
+ componentName: context.name,
15996
+ env: context.env,
15997
+ isReviewEnv: context.environment.envType === "review",
15998
+ deployConfig: deployConfig && deployConfig.type === "google-cloudrun"
15999
+ ? deployConfig
16000
+ : null,
16001
+ config: context.fullConfig,
16002
+ };
16003
+ };
16004
+ const fromEnvironmentContext = (context) => ({
16005
+ fullName: context.fullName,
16006
+ environmentSlugPrefix: context.environmentSlugPrefix,
16007
+ componentName: context.componentName,
16008
+ env: context.env,
16009
+ isReviewEnv: context.envType === "review",
16010
+ deployConfig: context.deployConfigRaw || null,
16011
+ config: context.fullConfig,
16012
+ });
16013
+ /**
16014
+ * the cloud run service name as it is passed to `gcloud run` — lowercased,
16015
+ * and shortened when the deterministic url would otherwise not fit.
16016
+ */
16017
+ const getServiceName = (context) => getRawServiceName(fromComponentContext(context)).toLowerCase();
15838
16018
  exports.getServiceName = getServiceName;
15839
- const getServiceNameForEnvContext = (context) => context.fullName.toLowerCase();
16019
+ const getServiceNameForEnvContext = (context) => getRawServiceName(fromEnvironmentContext(context)).toLowerCase();
15840
16020
  exports.getServiceNameForEnvContext = getServiceNameForEnvContext;
16021
+ /**
16022
+ * the service name part of the deterministic url, still to be lowercased
16023
+ * together with the rest of the hostname by the caller.
16024
+ */
16025
+ const getRawServiceNameForEnvContext = (context) => getRawServiceName(fromEnvironmentContext(context));
16026
+ exports.getRawServiceNameForEnvContext = getRawServiceNameForEnvContext;
15841
16027
  //# sourceMappingURL=getServiceName.js.map
15842
16028
 
15843
16029
  /***/ }),
@@ -18254,7 +18440,7 @@ exports.getRunnerImage = getRunnerImage;
18254
18440
  "use strict";
18255
18441
 
18256
18442
  Object.defineProperty(exports, "__esModule", ({ value: true }));
18257
- exports.getGcloudProjectNumber = exports.readCatladderStore = exports.getCatladderStorePath = exports.catladderStoreSchema = exports.CATLADDER_STORE_FILE = exports.CATLADDER_STORE_FILE_NAME = exports.CATLADDER_STORE_DIR = void 0;
18443
+ exports.getGcloudProjectNumber = exports.readGcloudProjectNumber = exports.readCatladderStore = exports.getCatladderStorePath = exports.catladderStoreSchema = exports.CATLADDER_STORE_FILE = exports.CATLADDER_STORE_FILE_NAME = exports.CATLADDER_STORE_DIR = void 0;
18258
18444
  const fs_1 = __nccwpck_require__(79896);
18259
18445
  const path_1 = __nccwpck_require__(16928);
18260
18446
  const yaml_1 = __nccwpck_require__(99292);
@@ -18306,6 +18492,13 @@ const readCatladderStore = (directory = process.cwd()) => {
18306
18492
  }
18307
18493
  };
18308
18494
  exports.readCatladderStore = readCatladderStore;
18495
+ /**
18496
+ * gcloud project number from the store, or null when it has not been
18497
+ * fetched yet. Use this where a missing number is not itself the problem —
18498
+ * `getGcloudProjectNumber` is the one that reports it.
18499
+ */
18500
+ const readGcloudProjectNumber = (config, projectId) => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.store) === null || _a === void 0 ? void 0 : _a.gcloudProjects) === null || _b === void 0 ? void 0 : _b[projectId]) === null || _c === void 0 ? void 0 : _c.projectNumber) !== null && _d !== void 0 ? _d : null; };
18501
+ exports.readGcloudProjectNumber = readGcloudProjectNumber;
18309
18502
  /**
18310
18503
  * gcloud project number from the store — needed to compute deterministic
18311
18504
  * cloud run urls (`<service>-<projectNumber>.<region>.run.app`) at
@@ -18315,8 +18508,7 @@ exports.readCatladderStore = readCatladderStore;
18315
18508
  * catenv fail until `catladder project setup` has stored it.
18316
18509
  */
18317
18510
  const getGcloudProjectNumber = (config, projectId) => {
18318
- var _a, _b, _c;
18319
- const projectNumber = (_c = (_b = (_a = config.store) === null || _a === void 0 ? void 0 : _a.gcloudProjects) === null || _b === void 0 ? void 0 : _b[projectId]) === null || _c === void 0 ? void 0 : _c.projectNumber;
18511
+ const projectNumber = (0, exports.readGcloudProjectNumber)(config, projectId);
18320
18512
  if (!projectNumber) {
18321
18513
  throw new Error(`Missing gcloud project number for project "${projectId}" in ${exports.CATLADDER_STORE_FILE}.\n` +
18322
18514
  `Run "catladder project setup" to fetch and store it.`);
@@ -46,6 +46,7 @@ resources with `yarn catladder project setup`; detect drift with
46
46
  - `cloudSql?: DeployConfigCloudRunCloudSql | false` — `{ type: "unmanaged", instanceConnectionName, dbUser?, dbNamePrefix?, dbBaseName?, deleteDatabaseOnStop?, dbConnectionStringFormat? ("prisma" default | "rails" | "jdbc"), dbConnectionStringVariablesMode? ("embedded" default | "legacy"), dbAdditionalQueryParams? }`. Injects `DB_*` vars plus `DATABASE_URL`/`DATABASE_JDBC_URL`; in the default `"embedded"` mode the connection strings contain the component's final values (referenceable from other components, `vars.public` overrides of `DB_*` flow in). To share another component's database: `dbBaseName: "<owner>"` + `DB_PASSWORD: "${<owner>:DB_PASSWORD}"` in `vars.public`.
47
47
  - `execute?: Record<string, DeployConfigCloudRunExecute | null>` — run a script / job / HTTP call at a lifecycle point (`when`: `preDeploy` | `postDeploy` | `preStop` | `postStop`) or on a `schedule`.
48
48
  - `debug?: boolean`.
49
+ - Service name and url: the service deploys as `<customerName>-<appName>-<env>[-<reviewSlug>]-<componentName>`, and `ROOT_URL`/`ROOT_URL_INTERNAL` are cloud run's deterministic url `https://<service>-<projectNumber>.<region>.run.app`. That url only exists while its first dns label stays within 63 characters, so catladder **shortens the component part** of the service name when it would not fit — otherwise cloud run would serve a legacy url with a random identifier and the generated hostname would never resolve. Review environments carry a runtime slug on top, for which 8 characters are reserved, so a name can fit `dev`/`prod` and still be shortened for `review`. Generation fails instead of shortening when two components would end up with the same name, or when customerName/appName/env/project number already leave no room.
49
50
 
50
51
  ## `npmPackage`
51
52
 
@@ -65,9 +65,14 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
65
65
  // generation time. For review envs the service name part still
66
66
  // contains a runtime expression (the review slug), so the host stays
67
67
  // a bash expression there; the suffix is always a literal.
68
+ //
69
+ // The service name has to come from getRawServiceNameForEnvContext,
70
+ // not from fullName: it is shortened when the label would otherwise
71
+ // exceed what cloud run serves deterministically, and the url must
72
+ // name the service that is actually deployed.
68
73
  const HOSTNAME_INTERNAL = deployConfigRaw && envType !== "local"
69
74
  ? (0, bash_1.joinBashExpressions)([
70
- fullName,
75
+ (0, getServiceName_1.getRawServiceNameForEnvContext)(ctx),
71
76
  `${(0, store_1.getGcloudProjectNumber)(fullConfig, deployConfigRaw.projectId)}.${deployConfigRaw.region}.run.app`,
72
77
  ], "-").toLowerCase()
73
78
  : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../packages/pipeline/src/deploy/cloudRun/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../packages/pipeline/src/deploy/cloudRun/index.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,74 @@
1
+ import type { StringOrBashExpression } from "../../../../../bash/src/index.js";
1
2
  import type { DeployConfigCloudRun } from "../..";
2
3
  import type { BuildConfig } from "../../../build/types";
3
4
  import type { ComponentContext } from "../../../types/context";
4
5
  import type { EnvironmentContext } from "../../../types/environmentContext";
6
+ /**
7
+ * cloud run only serves its deterministic url
8
+ * `https://<service>-<projectNumber>.<region>.run.app` while that first dns
9
+ * label stays within the 63 characters a dns label allows — the label holds
10
+ * the service name, the project number and any traffic tag together.
11
+ *
12
+ * Beyond it cloud run silently switches to a legacy url built from a random
13
+ * identifier that nothing can recompute. The url catladder generates would
14
+ * then be a hostname that can never resolve, and everything consuming
15
+ * ROOT_URL/ROOT_URL_INTERNAL (cloud tasks targets, service-to-service
16
+ * calls) fails with a dns error instead of a helpful one — which is why the
17
+ * component part is shortened to stay under the limit rather than left to
18
+ * overflow.
19
+ *
20
+ * https://cloud.google.com/run/docs/triggering/https-request
21
+ */
22
+ export declare const CLOUD_RUN_DNS_SEGMENT_LIMIT = 63;
23
+ /**
24
+ * review environments resolve their slug at runtime (`mr<iid>` on gitlab,
25
+ * `pr<number>` on github), so its exact length is unknown while generating.
26
+ * Budget for a six digit number so that service names — and with them the
27
+ * urls of already deployed services — do not start changing years later
28
+ * just because a project's merge request numbers grew a digit.
29
+ */
30
+ export declare const REVIEW_SLUG_LENGTH_BUDGET: number;
31
+ export type CloudRunComponentPartInput = {
32
+ customerName: string;
33
+ appName: string;
34
+ env: string;
35
+ /** whether the env resolves a review slug at runtime */
36
+ isReviewEnv: boolean;
37
+ componentName: string;
38
+ projectNumber: string;
39
+ /**
40
+ * the config's other component names, so that a shortened name colliding
41
+ * with a sibling's is caught while generating instead of at deploy time,
42
+ * where two components would fight over one cloud run service
43
+ */
44
+ otherComponentNames: string[];
45
+ };
46
+ export type CloudRunComponentPart = {
47
+ /** the component part of the service name, shortened if it had to be */
48
+ value: string;
49
+ /** characters dropped from the component name — 0 when it already fit */
50
+ dropped: number;
51
+ /** dns label length of the resulting url, review slug budget included */
52
+ dnsSegmentLength: number;
53
+ };
54
+ /**
55
+ * the component-name part of a cloud run service name, shortened just
56
+ * enough to keep the deterministic url resolvable.
57
+ *
58
+ * Only the component part is shortened: the env and review slug parts have
59
+ * to stay intact (they are what makes the name unique per environment), the
60
+ * project number is fixed, and customerName/appName are shared by every
61
+ * service of the project.
62
+ */
63
+ export declare const resolveCloudRunComponentPart: ({ customerName, appName, env, isReviewEnv, componentName, projectNumber, otherComponentNames, }: CloudRunComponentPartInput) => CloudRunComponentPart;
64
+ /**
65
+ * the cloud run service name as it is passed to `gcloud run` — lowercased,
66
+ * and shortened when the deterministic url would otherwise not fit.
67
+ */
5
68
  export declare const getServiceName: (context: ComponentContext) => string | import("../../../../../bash/src/index.js").BashExpression;
6
69
  export declare const getServiceNameForEnvContext: (context: EnvironmentContext<BuildConfig, DeployConfigCloudRun>) => string | import("../../../../../bash/src/index.js").BashExpression;
70
+ /**
71
+ * the service name part of the deterministic url, still to be lowercased
72
+ * together with the rest of the hostname by the caller.
73
+ */
74
+ export declare const getRawServiceNameForEnvContext: (context: EnvironmentContext<BuildConfig, DeployConfigCloudRun>) => StringOrBashExpression;