@catladder/cli 0.0.0-next-88a07ab6 → 0.0.0-next-51dc9c2b
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/bundles/catenv/index.js +151 -4
- package/dist/bundles/cli/index.js +923 -43
- package/dist/cli/src/apps/cli/commands/project/doctor/DoctorReport.d.ts +22 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/DoctorReport.js +75 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/DoctorReport.js.map +1 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/GcloudProjectInspector.d.ts +15 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/GcloudProjectInspector.js +59 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/GcloudProjectInspector.js.map +1 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkCloudRun.d.ts +13 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkCloudRun.js +120 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkCloudRun.js.map +1 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkGithub.d.ts +10 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkGithub.js +100 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkGithub.js.map +1 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkGitlab.d.ts +13 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkGitlab.js +79 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkGitlab.js.map +1 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkStore.d.ts +8 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkStore.js +44 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/checkStore.js.map +1 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/index.d.ts +14 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/index.js +48 -0
- package/dist/cli/src/apps/cli/commands/project/doctor/index.js.map +1 -0
- package/dist/cli/src/apps/cli/commands/project/setup/setupAccessTokens.js +4 -1
- package/dist/cli/src/apps/cli/commands/project/setup/setupAccessTokens.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/project/setup/setupCloudRun.d.ts +21 -0
- package/dist/cli/src/apps/cli/commands/project/setup/setupCloudRun.js +31 -11
- package/dist/cli/src/apps/cli/commands/project/setup/setupCloudRun.js.map +1 -1
- package/dist/cli/src/commands/index.d.ts +1 -0
- package/dist/cli/src/commands/index.js +8 -1
- package/dist/cli/src/commands/index.js.map +1 -1
- package/dist/cli/src/commands/project/commandDoctor.d.ts +8 -0
- package/dist/cli/src/commands/project/commandDoctor.js +25 -0
- package/dist/cli/src/commands/project/commandDoctor.js.map +1 -0
- package/dist/cli/src/gcloud/artifactsRegistry.d.ts +1 -0
- package/dist/cli/src/gcloud/artifactsRegistry.js +3 -2
- package/dist/cli/src/gcloud/artifactsRegistry.js.map +1 -1
- package/dist/cli/src/gcloud/serviceAccountNames.d.ts +28 -0
- package/dist/cli/src/gcloud/serviceAccountNames.js +51 -0
- package/dist/cli/src/gcloud/serviceAccountNames.js.map +1 -0
- package/dist/cli/src/gcloud/serviceAccounts.js +6 -27
- package/dist/cli/src/gcloud/serviceAccounts.js.map +1 -1
- package/dist/cli/src/utils/concurrency.d.ts +7 -0
- package/dist/cli/src/utils/concurrency.js +27 -0
- package/dist/cli/src/utils/concurrency.js.map +1 -0
- package/dist/cli/src/utils/github.d.ts +10 -0
- package/dist/cli/src/utils/github.js +26 -1
- package/dist/cli/src/utils/github.js.map +1 -1
- package/dist/cli/src/utils/gitlab.d.ts +6 -0
- package/dist/cli/src/utils/gitlab.js +19 -1
- package/dist/cli/src/utils/gitlab.js.map +1 -1
- package/dist/pipeline/src/constants.js +1 -1
- package/dist/pipeline/src/deploy/cloudRun/index.js +12 -0
- package/dist/pipeline/src/deploy/cloudRun/index.js.map +1 -1
- package/dist/pipeline/src/deploy/index.d.ts +5 -0
- package/dist/pipeline/src/deploy/index.js.map +1 -1
- package/dist/pipeline/src/index.d.ts +1 -0
- package/dist/pipeline/src/index.js +1 -0
- package/dist/pipeline/src/index.js.map +1 -1
- package/dist/pipeline/src/pipeline/createJobsForComponent.js +3 -2
- package/dist/pipeline/src/pipeline/createJobsForComponent.js.map +1 -1
- package/dist/pipeline/src/types/config.d.ts +8 -0
- package/dist/pipeline/src/types/config.js.map +1 -1
- package/dist/pipeline/src/verify/createVerifyJobs.d.ts +4 -0
- package/dist/pipeline/src/verify/createVerifyJobs.js +63 -0
- package/dist/pipeline/src/verify/createVerifyJobs.js.map +1 -0
- package/dist/pipeline/src/verify/index.d.ts +2 -0
- package/dist/pipeline/src/verify/index.js +26 -0
- package/dist/pipeline/src/verify/index.js.map +1 -0
- package/dist/pipeline/src/verify/types.d.ts +16 -0
- package/dist/pipeline/src/verify/types.js +5 -0
- package/dist/pipeline/src/verify/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/apps/cli/commands/project/doctor/DoctorReport.ts +72 -0
- package/src/apps/cli/commands/project/doctor/GcloudProjectInspector.ts +77 -0
- package/src/apps/cli/commands/project/doctor/checkCloudRun.ts +148 -0
- package/src/apps/cli/commands/project/doctor/checkGithub.ts +156 -0
- package/src/apps/cli/commands/project/doctor/checkGitlab.ts +133 -0
- package/src/apps/cli/commands/project/doctor/checkStore.ts +43 -0
- package/src/apps/cli/commands/project/doctor/index.ts +59 -0
- package/src/apps/cli/commands/project/setup/setupAccessTokens.ts +9 -2
- package/src/apps/cli/commands/project/setup/setupCloudRun.ts +42 -21
- package/src/commands/index.ts +1 -0
- package/src/commands/project/commandDoctor.ts +21 -0
- package/src/gcloud/__tests__/serviceAccountNames.test.ts +63 -0
- package/src/gcloud/artifactsRegistry.ts +3 -1
- package/src/gcloud/serviceAccountNames.ts +65 -0
- package/src/gcloud/serviceAccounts.ts +6 -38
- package/src/utils/concurrency.ts +25 -0
- package/src/utils/github.ts +48 -0
- package/src/utils/gitlab.ts +24 -0
- package/tsconfig.json +2 -1
|
@@ -587,6 +587,580 @@ exports.projectConfigSecrets = projectConfigSecrets;
|
|
|
587
587
|
|
|
588
588
|
/***/ }),
|
|
589
589
|
|
|
590
|
+
/***/ 88089:
|
|
591
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
592
|
+
|
|
593
|
+
"use strict";
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
597
|
+
value: true
|
|
598
|
+
}));
|
|
599
|
+
exports.DoctorReport = void 0;
|
|
600
|
+
/**
|
|
601
|
+
* collects the results of all doctor checks: each check logs
|
|
602
|
+
* immediately (progressive output like `project setup`) and problems
|
|
603
|
+
* are repeated in the final summary together with the command that
|
|
604
|
+
* heals them. The report itself never mutates anything — doctor
|
|
605
|
+
* diagnoses, setup heals.
|
|
606
|
+
*/
|
|
607
|
+
class DoctorReport {
|
|
608
|
+
constructor(io) {
|
|
609
|
+
this.io = io;
|
|
610
|
+
this.passed = 0;
|
|
611
|
+
this.warnings = [];
|
|
612
|
+
this.problems = [];
|
|
613
|
+
this.currentSection = "";
|
|
614
|
+
}
|
|
615
|
+
section(title) {
|
|
616
|
+
this.currentSection = title;
|
|
617
|
+
this.io.log("");
|
|
618
|
+
this.io.log("🩺 " + title);
|
|
619
|
+
}
|
|
620
|
+
ok(message) {
|
|
621
|
+
this.passed++;
|
|
622
|
+
this.io.log(" ✅ " + message);
|
|
623
|
+
}
|
|
624
|
+
warn(message, remediation) {
|
|
625
|
+
this.warnings.push({
|
|
626
|
+
section: this.currentSection,
|
|
627
|
+
message,
|
|
628
|
+
remediation
|
|
629
|
+
});
|
|
630
|
+
this.io.log(" ⚠️ " + message);
|
|
631
|
+
if (remediation) this.io.log(" ↳ " + remediation);
|
|
632
|
+
}
|
|
633
|
+
fail(message, remediation) {
|
|
634
|
+
this.problems.push({
|
|
635
|
+
section: this.currentSection,
|
|
636
|
+
message,
|
|
637
|
+
remediation
|
|
638
|
+
});
|
|
639
|
+
this.io.log(" ❌ " + message);
|
|
640
|
+
if (remediation) this.io.log(" ↳ " + remediation);
|
|
641
|
+
}
|
|
642
|
+
get hasProblems() {
|
|
643
|
+
return this.problems.length > 0;
|
|
644
|
+
}
|
|
645
|
+
summarize() {
|
|
646
|
+
const {
|
|
647
|
+
io
|
|
648
|
+
} = this;
|
|
649
|
+
io.log("");
|
|
650
|
+
io.log("==================================================================================");
|
|
651
|
+
io.log(`🩺 doctor summary: ${this.passed} checks passed, ` + `${this.warnings.length} warnings, ${this.problems.length} problems`);
|
|
652
|
+
if (!this.hasProblems) {
|
|
653
|
+
io.log("");
|
|
654
|
+
io.log("everything looks healthy 😻");
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
io.log("");
|
|
658
|
+
for (const {
|
|
659
|
+
section,
|
|
660
|
+
message,
|
|
661
|
+
remediation
|
|
662
|
+
} of this.problems) {
|
|
663
|
+
io.log(`❌ [${section}] ${message}`);
|
|
664
|
+
if (remediation) io.log(` ↳ ${remediation}`);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
exports.DoctorReport = DoctorReport;
|
|
669
|
+
|
|
670
|
+
/***/ }),
|
|
671
|
+
|
|
672
|
+
/***/ 44952:
|
|
673
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
674
|
+
|
|
675
|
+
"use strict";
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
679
|
+
value: true
|
|
680
|
+
}));
|
|
681
|
+
exports.GcloudProjectInspector = void 0;
|
|
682
|
+
const child_process_promise_1 = __nccwpck_require__(51748);
|
|
683
|
+
const artifactsRegistry_1 = __nccwpck_require__(41624);
|
|
684
|
+
/**
|
|
685
|
+
* read-only gcloud queries for the doctor, cached per project: checking
|
|
686
|
+
* many component/env contexts of the same gcloud project costs one
|
|
687
|
+
* `get-iam-policy` / `services list` call, not one per context
|
|
688
|
+
*/
|
|
689
|
+
class GcloudProjectInspector {
|
|
690
|
+
constructor() {
|
|
691
|
+
this.iamBindings = new Map();
|
|
692
|
+
this.enabledServices = new Map();
|
|
693
|
+
}
|
|
694
|
+
async isAuthenticated() {
|
|
695
|
+
try {
|
|
696
|
+
await (0, child_process_promise_1.exec)("gcloud auth print-access-token");
|
|
697
|
+
return true;
|
|
698
|
+
} catch (_a) {
|
|
699
|
+
return false;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
getIamBindings(projectId) {
|
|
703
|
+
if (!this.iamBindings.has(projectId)) {
|
|
704
|
+
this.iamBindings.set(projectId, (0, child_process_promise_1.exec)(`gcloud projects get-iam-policy ${projectId} --format=json`).then(result => {
|
|
705
|
+
var _a;
|
|
706
|
+
return (_a = JSON.parse(result.stdout).bindings) !== null && _a !== void 0 ? _a : [];
|
|
707
|
+
}));
|
|
708
|
+
}
|
|
709
|
+
return this.iamBindings.get(projectId);
|
|
710
|
+
}
|
|
711
|
+
/** all roles bound to the given member (e.g. "serviceAccount:<email>") */
|
|
712
|
+
async getRolesOfMember(projectId, member) {
|
|
713
|
+
const bindings = await this.getIamBindings(projectId);
|
|
714
|
+
return bindings.filter(binding => {
|
|
715
|
+
var _a;
|
|
716
|
+
return (_a = binding.members) === null || _a === void 0 ? void 0 : _a.includes(member);
|
|
717
|
+
}).map(binding => binding.role);
|
|
718
|
+
}
|
|
719
|
+
getEnabledServices(projectId) {
|
|
720
|
+
if (!this.enabledServices.has(projectId)) {
|
|
721
|
+
this.enabledServices.set(projectId, (0, child_process_promise_1.exec)(`gcloud services list --enabled --project=${projectId} --format="value(config.name)"`).then(result => new Set(result.stdout.split("\n").map(line => line.trim()).filter(Boolean))));
|
|
722
|
+
}
|
|
723
|
+
return this.enabledServices.get(projectId);
|
|
724
|
+
}
|
|
725
|
+
async hasArtifactsRegistry(projectId, region) {
|
|
726
|
+
try {
|
|
727
|
+
await (0, child_process_promise_1.exec)(`gcloud artifacts repositories describe ${artifactsRegistry_1.CATLADDER_REGISTRY_NAME} --project="${projectId}" --location=${region}`);
|
|
728
|
+
return true;
|
|
729
|
+
} catch (_a) {
|
|
730
|
+
return false;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
exports.GcloudProjectInspector = GcloudProjectInspector;
|
|
735
|
+
|
|
736
|
+
/***/ }),
|
|
737
|
+
|
|
738
|
+
/***/ 65424:
|
|
739
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
740
|
+
|
|
741
|
+
"use strict";
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
745
|
+
value: true
|
|
746
|
+
}));
|
|
747
|
+
exports.checkCloudRun = void 0;
|
|
748
|
+
const pipeline_1 = __nccwpck_require__(60241);
|
|
749
|
+
const artifactsRegistry_1 = __nccwpck_require__(41624);
|
|
750
|
+
const serviceAccountNames_1 = __nccwpck_require__(83798);
|
|
751
|
+
const serviceAccounts_1 = __nccwpck_require__(35611);
|
|
752
|
+
const concurrency_1 = __nccwpck_require__(5092);
|
|
753
|
+
const setupCloudRun_1 = __nccwpck_require__(51629);
|
|
754
|
+
const GcloudProjectInspector_1 = __nccwpck_require__(44952);
|
|
755
|
+
const getCloudRunConfig = context => {
|
|
756
|
+
var _a;
|
|
757
|
+
const config = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
|
|
758
|
+
if (!(0, pipeline_1.isOfDeployType)(config, "google-cloudrun")) {
|
|
759
|
+
throw new Error("not a cloud run context");
|
|
760
|
+
}
|
|
761
|
+
return config;
|
|
762
|
+
};
|
|
763
|
+
/**
|
|
764
|
+
* compares the gcloud state `setupCloudRun` would provision for the
|
|
765
|
+
* CURRENT config against what is actually there: enabled services and
|
|
766
|
+
* artifacts registry per project, deploy service account existence and
|
|
767
|
+
* IAM roles per component/env.
|
|
768
|
+
*
|
|
769
|
+
* The motivating case (#70): a component gets `cloudSql` after its
|
|
770
|
+
* setup ran — deploys keep working and only the review teardown hits
|
|
771
|
+
* the missing `roles/cloudsql.admin` as a 403 in ci.
|
|
772
|
+
*/
|
|
773
|
+
const checkCloudRun = async (report, contexts) => {
|
|
774
|
+
var _a;
|
|
775
|
+
const cloudRunContexts = contexts.filter(context => {
|
|
776
|
+
var _a;
|
|
777
|
+
return (0, pipeline_1.isOfDeployType)((_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config, "google-cloudrun");
|
|
778
|
+
});
|
|
779
|
+
if (cloudRunContexts.length === 0) return;
|
|
780
|
+
report.section("google cloud run infrastructure");
|
|
781
|
+
const inspector = new GcloudProjectInspector_1.GcloudProjectInspector();
|
|
782
|
+
if (!(await inspector.isAuthenticated())) {
|
|
783
|
+
report.fail("gcloud is not authenticated — all google cloud checks skipped", "run: gcloud auth login");
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
// project-level: enabled services + artifacts registry. The required
|
|
787
|
+
// services are the union over all components deploying to the project
|
|
788
|
+
// (cloudSql on any of them requires the sql services).
|
|
789
|
+
const byProject = new Map();
|
|
790
|
+
for (const context of cloudRunContexts) {
|
|
791
|
+
const {
|
|
792
|
+
projectId
|
|
793
|
+
} = getCloudRunConfig(context);
|
|
794
|
+
byProject.set(projectId, [...((_a = byProject.get(projectId)) !== null && _a !== void 0 ? _a : []), context]);
|
|
795
|
+
}
|
|
796
|
+
for (const [projectId, projectContexts] of byProject) {
|
|
797
|
+
const requiredServices = new Set(projectContexts.flatMap(context => (0, setupCloudRun_1.getCloudRunRequiredServices)(getCloudRunConfig(context))));
|
|
798
|
+
try {
|
|
799
|
+
const enabled = await inspector.getEnabledServices(projectId);
|
|
800
|
+
const missing = [...requiredServices].filter(service => !enabled.has(service));
|
|
801
|
+
if (missing.length === 0) {
|
|
802
|
+
report.ok(`${projectId}: all ${requiredServices.size} required services enabled`);
|
|
803
|
+
} else {
|
|
804
|
+
report.fail(`${projectId}: services not enabled: ${missing.join(", ")}`, "run: catladder project setup");
|
|
805
|
+
}
|
|
806
|
+
} catch (e) {
|
|
807
|
+
report.warn(`${projectId}: could not list enabled services (${e.message})`);
|
|
808
|
+
}
|
|
809
|
+
const regions = new Set(projectContexts.map(context => getCloudRunConfig(context).region));
|
|
810
|
+
for (const region of regions) {
|
|
811
|
+
if (await inspector.hasArtifactsRegistry(projectId, region)) {
|
|
812
|
+
report.ok(`${projectId}: artifacts registry '${artifactsRegistry_1.CATLADDER_REGISTRY_NAME}' exists in ${region}`);
|
|
813
|
+
} else {
|
|
814
|
+
report.fail(`${projectId}: artifacts registry '${artifactsRegistry_1.CATLADDER_REGISTRY_NAME}' missing in ${region}`, "run: catladder project setup");
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
// per component/env: deploy service account exists and carries every
|
|
819
|
+
// role the current config implies
|
|
820
|
+
const results = await (0, concurrency_1.mapWithConcurrency)(cloudRunContexts, 5, async context => {
|
|
821
|
+
const config = getCloudRunConfig(context);
|
|
822
|
+
const {
|
|
823
|
+
fullIdentifier
|
|
824
|
+
} = (0, serviceAccountNames_1.getGcloudServiceAccountNames)(context, {
|
|
825
|
+
name: setupCloudRun_1.CLOUD_RUN_DEPLOY_SA_NAME,
|
|
826
|
+
projectId: config.projectId
|
|
827
|
+
});
|
|
828
|
+
if (!(await (0, serviceAccounts_1.accountExists)(fullIdentifier))) {
|
|
829
|
+
return {
|
|
830
|
+
context,
|
|
831
|
+
fullIdentifier,
|
|
832
|
+
exists: false,
|
|
833
|
+
missingRoles: []
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
const boundRoles = await inspector.getRolesOfMember(config.projectId, `serviceAccount:${fullIdentifier}`);
|
|
837
|
+
const missingRoles = (0, setupCloudRun_1.getCloudRunDeployRoles)(config).filter(role => !boundRoles.includes(role));
|
|
838
|
+
return {
|
|
839
|
+
context,
|
|
840
|
+
fullIdentifier,
|
|
841
|
+
exists: true,
|
|
842
|
+
missingRoles
|
|
843
|
+
};
|
|
844
|
+
});
|
|
845
|
+
for (const {
|
|
846
|
+
context,
|
|
847
|
+
fullIdentifier,
|
|
848
|
+
exists,
|
|
849
|
+
missingRoles
|
|
850
|
+
} of results) {
|
|
851
|
+
const label = `${context.env}:${context.name}`;
|
|
852
|
+
if (!exists) {
|
|
853
|
+
report.fail(`${label}: deploy service account ${fullIdentifier} does not exist`, `run: catladder project setup ${context.name}`);
|
|
854
|
+
} else if (missingRoles.length > 0) {
|
|
855
|
+
report.fail(`${label}: service account is missing roles: ${missingRoles.join(", ")}`, `run: catladder project setup ${context.name}`);
|
|
856
|
+
} else {
|
|
857
|
+
report.ok(`${label}: service account exists with all config-implied roles`);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
exports.checkCloudRun = checkCloudRun;
|
|
862
|
+
|
|
863
|
+
/***/ }),
|
|
864
|
+
|
|
865
|
+
/***/ 93265:
|
|
866
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
867
|
+
|
|
868
|
+
"use strict";
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
872
|
+
value: true
|
|
873
|
+
}));
|
|
874
|
+
exports.checkGithub = void 0;
|
|
875
|
+
const pipeline_1 = __nccwpck_require__(60241);
|
|
876
|
+
const commandSecretsSyncGithub_1 = __nccwpck_require__(50962);
|
|
877
|
+
const concurrency_1 = __nccwpck_require__(5092);
|
|
878
|
+
const github_1 = __nccwpck_require__(18036);
|
|
879
|
+
/** marker for repo-level (environment-less) targets, see collectSecretTargets */
|
|
880
|
+
const REPO_LEVEL = "";
|
|
881
|
+
/**
|
|
882
|
+
* compares the secret/variable NAMES the generated github workflows
|
|
883
|
+
* reference against what is actually set — per github environment, the
|
|
884
|
+
* same mapping `project secrets-sync-github` writes. Values cannot be
|
|
885
|
+
* compared: github secrets are write-only by design (the vault stays
|
|
886
|
+
* the source of truth).
|
|
887
|
+
*/
|
|
888
|
+
const checkGithub = async (report, config) => {
|
|
889
|
+
if (!(0, pipeline_1.getEnabledPipelineTypes)(config).includes("github")) return;
|
|
890
|
+
report.section("github environments & secrets");
|
|
891
|
+
if (!(await (0, github_1.isGhAuthenticated)())) {
|
|
892
|
+
report.warn("github cli (gh) not authenticated — github checks skipped", "run: gh auth login");
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
const repo = await (0, commandSecretsSyncGithub_1.getConfiguredGithubRepo)();
|
|
896
|
+
if (!repo) {
|
|
897
|
+
report.fail(`no github repository found on the '${(0, pipeline_1.getPipelineGitRemote)(config, "github")}' remote`);
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
let targets;
|
|
901
|
+
try {
|
|
902
|
+
targets = await (0, commandSecretsSyncGithub_1.collectSecretTargets)(config);
|
|
903
|
+
} catch (e) {
|
|
904
|
+
report.warn(`could not generate the github workflows to derive secret references (${e.message})`);
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
const referencedNamesOf = environment => [...targets.entries()].filter(([, envs]) => envs.has(environment)).map(([name]) => name);
|
|
908
|
+
const environmentsNeeded = [...new Set([...targets.values()].flatMap(envs => [...envs]))].filter(environment => environment !== REPO_LEVEL).sort();
|
|
909
|
+
let existingEnvironments;
|
|
910
|
+
try {
|
|
911
|
+
existingEnvironments = new Set(await (0, github_1.listGithubEnvironments)(repo));
|
|
912
|
+
} catch (e) {
|
|
913
|
+
report.warn(`could not list environments of ${repo} (${e.message})`);
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
const perEnvironment = await (0, concurrency_1.mapWithConcurrency)(environmentsNeeded, 8, async environment => {
|
|
917
|
+
const referenced = referencedNamesOf(environment);
|
|
918
|
+
if (!existingEnvironments.has(environment)) {
|
|
919
|
+
return {
|
|
920
|
+
environment,
|
|
921
|
+
referenced,
|
|
922
|
+
exists: false
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
const [secrets, variables] = await Promise.all([(0, github_1.listGithubSecretNames)(repo, environment), (0, github_1.listGithubVariableNames)(repo, environment)]);
|
|
926
|
+
// github secret names are case-insensitive and the api returns
|
|
927
|
+
// them uppercased — compare accordingly
|
|
928
|
+
const present = new Set([...secrets, ...variables].map(name => name.toUpperCase()));
|
|
929
|
+
const referencedUpper = new Set(referenced.map(name => name.toUpperCase()));
|
|
930
|
+
return {
|
|
931
|
+
environment,
|
|
932
|
+
referenced,
|
|
933
|
+
exists: true,
|
|
934
|
+
missing: referenced.filter(name => !present.has(name.toUpperCase())),
|
|
935
|
+
stale: [...present].filter(name => !referencedUpper.has(name))
|
|
936
|
+
};
|
|
937
|
+
});
|
|
938
|
+
for (const result of perEnvironment) {
|
|
939
|
+
const {
|
|
940
|
+
environment,
|
|
941
|
+
referenced
|
|
942
|
+
} = result;
|
|
943
|
+
if (!result.exists) {
|
|
944
|
+
report.fail(`environment '${environment}' does not exist (${referenced.length} referenced secrets have nowhere to live)`, "run: catladder project secrets-sync-github");
|
|
945
|
+
continue;
|
|
946
|
+
}
|
|
947
|
+
if (result.missing.length > 0) {
|
|
948
|
+
report.fail(`${environment}: missing ${result.missing.length}/${referenced.length} referenced secrets: ${result.missing.join(", ")}`, "run: catladder project secrets-sync-github");
|
|
949
|
+
} else {
|
|
950
|
+
report.ok(`${environment}: all ${referenced.length} referenced secrets/variables present`);
|
|
951
|
+
}
|
|
952
|
+
if (result.stale.length > 0) {
|
|
953
|
+
report.warn(`${environment}: ${result.stale.length} set but not referenced by any workflow (stale?): ${result.stale.join(", ")}`);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
const repoLevelReferenced = referencedNamesOf(REPO_LEVEL);
|
|
957
|
+
if (repoLevelReferenced.length > 0) {
|
|
958
|
+
const [secrets, variables] = await Promise.all([(0, github_1.listGithubSecretNames)(repo), (0, github_1.listGithubVariableNames)(repo)]);
|
|
959
|
+
const present = new Set([...secrets, ...variables].map(name => name.toUpperCase()));
|
|
960
|
+
const missing = repoLevelReferenced.filter(name => !present.has(name.toUpperCase()));
|
|
961
|
+
if (missing.length > 0) {
|
|
962
|
+
report.fail(`repo level: missing ${missing.length}/${repoLevelReferenced.length} referenced secrets: ${missing.join(", ")}`, "run: catladder project secrets-sync-github");
|
|
963
|
+
} else {
|
|
964
|
+
report.ok(`repo level: all ${repoLevelReferenced.length} referenced secrets/variables present`);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
exports.checkGithub = checkGithub;
|
|
969
|
+
|
|
970
|
+
/***/ }),
|
|
971
|
+
|
|
972
|
+
/***/ 47273:
|
|
973
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
974
|
+
|
|
975
|
+
"use strict";
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
979
|
+
value: true
|
|
980
|
+
}));
|
|
981
|
+
exports.checkGitlab = void 0;
|
|
982
|
+
const pipeline_1 = __nccwpck_require__(60241);
|
|
983
|
+
const date_fns_1 = __nccwpck_require__(84022);
|
|
984
|
+
const gitlab_1 = __nccwpck_require__(4508);
|
|
985
|
+
const EXPIRY_WARNING_DAYS = 30;
|
|
986
|
+
/**
|
|
987
|
+
* the gitlab-side outputs of `project setup`: the semantic-release
|
|
988
|
+
* access token (+ its GL_TOKEN ci variable), the catladder topic and —
|
|
989
|
+
* for kubernetes deploys — the registry deploy token.
|
|
990
|
+
*
|
|
991
|
+
* Kubernetes namespace/rbac checks are deliberately skipped: they would
|
|
992
|
+
* require connecting kubectl to every cluster, which switches the local
|
|
993
|
+
* kubeconfig context — doctor must not change anything.
|
|
994
|
+
*/
|
|
995
|
+
const checkGitlab = async (instance, report, contexts) => {
|
|
996
|
+
report.section("gitlab project setup");
|
|
997
|
+
let projectId;
|
|
998
|
+
try {
|
|
999
|
+
projectId = (await (0, gitlab_1.getProjectInfo)(instance)).id;
|
|
1000
|
+
} catch (e) {
|
|
1001
|
+
report.warn(`could not reach the gitlab api — gitlab checks skipped (${e.message})`);
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
try {
|
|
1005
|
+
const tokens = await (0, gitlab_1.doGitlabRequestAllPages)(instance, `projects/${projectId}/access_tokens`);
|
|
1006
|
+
const activeTokens = tokens.filter(t => t.name === "semantic-release" && t.active === true);
|
|
1007
|
+
// the GL_TOKEN ci variable holds exactly one of them — judge by the
|
|
1008
|
+
// one that lives longest
|
|
1009
|
+
const token = activeTokens.sort((a, b) => String(b.expires_at).localeCompare(String(a.expires_at)))[0];
|
|
1010
|
+
if (activeTokens.length > 1) {
|
|
1011
|
+
report.warn(`${activeTokens.length} active 'semantic-release' tokens exist — duplicates from earlier setups, consider revoking the old ones`);
|
|
1012
|
+
}
|
|
1013
|
+
if (!token) {
|
|
1014
|
+
report.fail("no active 'semantic-release' project access token", "run: catladder project setup");
|
|
1015
|
+
} else {
|
|
1016
|
+
const daysLeft = (0, date_fns_1.differenceInCalendarDays)(new Date(token.expires_at), new Date());
|
|
1017
|
+
if (daysLeft < 0) {
|
|
1018
|
+
report.fail(`'semantic-release' token expired on ${token.expires_at}`, "run: catladder project setup (rotates the token)");
|
|
1019
|
+
} else if (daysLeft <= EXPIRY_WARNING_DAYS) {
|
|
1020
|
+
report.warn(`'semantic-release' token expires in ${daysLeft} days (${token.expires_at})`, "run: catladder project setup (rotates the token)");
|
|
1021
|
+
} else {
|
|
1022
|
+
report.ok(`'semantic-release' token active (expires ${token.expires_at})`);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
try {
|
|
1026
|
+
await (0, gitlab_1.doGitlabRequest)(instance, `projects/${projectId}/variables/GL_TOKEN`);
|
|
1027
|
+
report.ok("GL_TOKEN ci variable present");
|
|
1028
|
+
} catch (_a) {
|
|
1029
|
+
report.fail("GL_TOKEN ci variable missing", "run: catladder project setup");
|
|
1030
|
+
}
|
|
1031
|
+
const {
|
|
1032
|
+
topics
|
|
1033
|
+
} = await (0, gitlab_1.doGitlabRequest)(instance, `projects/${projectId}`);
|
|
1034
|
+
if (topics === null || topics === void 0 ? void 0 : topics.includes("catladder")) {
|
|
1035
|
+
report.ok("'catladder' project topic set");
|
|
1036
|
+
} else {
|
|
1037
|
+
report.fail("'catladder' project topic missing", "run: catladder project setup");
|
|
1038
|
+
}
|
|
1039
|
+
if (contexts.some(context => {
|
|
1040
|
+
var _a;
|
|
1041
|
+
return (0, pipeline_1.isOfDeployType)((_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config, "kubernetes");
|
|
1042
|
+
})) {
|
|
1043
|
+
const deployTokens = await (0, gitlab_1.doGitlabRequestAllPages)(instance, `projects/${projectId}/deploy_tokens`);
|
|
1044
|
+
if (deployTokens.find(t => t.name === "gitlab-deploy-token")) {
|
|
1045
|
+
report.ok("'gitlab-deploy-token' registry deploy token present");
|
|
1046
|
+
} else {
|
|
1047
|
+
report.fail("'gitlab-deploy-token' registry deploy token missing (kubernetes cannot pull images)", "run: catladder project setup");
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
} catch (e) {
|
|
1051
|
+
report.warn(`gitlab checks aborted (${e.message})`);
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
exports.checkGitlab = checkGitlab;
|
|
1055
|
+
|
|
1056
|
+
/***/ }),
|
|
1057
|
+
|
|
1058
|
+
/***/ 21141:
|
|
1059
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
1060
|
+
|
|
1061
|
+
"use strict";
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
1065
|
+
value: true
|
|
1066
|
+
}));
|
|
1067
|
+
exports.checkStore = void 0;
|
|
1068
|
+
const pipeline_1 = __nccwpck_require__(60241);
|
|
1069
|
+
const getProjectConfig_1 = __nccwpck_require__(50001);
|
|
1070
|
+
const projects_1 = __nccwpck_require__(57414);
|
|
1071
|
+
/**
|
|
1072
|
+
* every google-cloudrun project in the config needs its project number
|
|
1073
|
+
* in the committed store — the deterministic cloud run urls
|
|
1074
|
+
* (<service>-<projectNumber>.<region>.run.app) are computed from it at
|
|
1075
|
+
* generation time. This check is fully offline.
|
|
1076
|
+
*/
|
|
1077
|
+
const checkStore = async report => {
|
|
1078
|
+
var _a, _b, _c;
|
|
1079
|
+
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
1080
|
+
const projectIds = new Set();
|
|
1081
|
+
for (const {
|
|
1082
|
+
componentName,
|
|
1083
|
+
env
|
|
1084
|
+
} of await (0, getProjectConfig_1.getAllComponentsWithAllEnvsFlat)()) {
|
|
1085
|
+
const {
|
|
1086
|
+
deploy
|
|
1087
|
+
} = (0, pipeline_1.getEnvConfig)(config, componentName, env);
|
|
1088
|
+
if (deploy && deploy.type === "google-cloudrun") {
|
|
1089
|
+
projectIds.add(deploy.projectId);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
if (projectIds.size === 0) return;
|
|
1093
|
+
report.section("catladder store (.catladder-store/store.yml)");
|
|
1094
|
+
const root = (_a = await (0, projects_1.getGitRoot)()) !== null && _a !== void 0 ? _a : process.cwd();
|
|
1095
|
+
const store = (0, pipeline_1.readCatladderStore)(root);
|
|
1096
|
+
for (const projectId of projectIds) {
|
|
1097
|
+
const projectNumber = (_c = (_b = store.gcloudProjects) === null || _b === void 0 ? void 0 : _b[projectId]) === null || _c === void 0 ? void 0 : _c.projectNumber;
|
|
1098
|
+
if (projectNumber) {
|
|
1099
|
+
report.ok(`project number for ${projectId}: ${projectNumber}`);
|
|
1100
|
+
} else {
|
|
1101
|
+
report.fail(`missing project number for ${projectId}`, "run: catladder project setup");
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
};
|
|
1105
|
+
exports.checkStore = checkStore;
|
|
1106
|
+
|
|
1107
|
+
/***/ }),
|
|
1108
|
+
|
|
1109
|
+
/***/ 96270:
|
|
1110
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
1111
|
+
|
|
1112
|
+
"use strict";
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
1116
|
+
value: true
|
|
1117
|
+
}));
|
|
1118
|
+
exports.doctorProject = void 0;
|
|
1119
|
+
const pipeline_1 = __nccwpck_require__(60241);
|
|
1120
|
+
const getProjectConfig_1 = __nccwpck_require__(50001);
|
|
1121
|
+
const checkCloudRun_1 = __nccwpck_require__(65424);
|
|
1122
|
+
const checkGithub_1 = __nccwpck_require__(93265);
|
|
1123
|
+
const checkGitlab_1 = __nccwpck_require__(47273);
|
|
1124
|
+
const checkStore_1 = __nccwpck_require__(21141);
|
|
1125
|
+
const DoctorReport_1 = __nccwpck_require__(88089);
|
|
1126
|
+
/**
|
|
1127
|
+
* read-only health check: compares the state `project setup` (and
|
|
1128
|
+
* `project secrets-sync-github`) would provision for the CURRENT config
|
|
1129
|
+
* against what is actually there, and reports drift together with the
|
|
1130
|
+
* command that heals it. `project setup` is a point-in-time
|
|
1131
|
+
* provisioner, so config edits that change required infrastructure
|
|
1132
|
+
* (IAM roles, services, secrets) drift silently until something breaks
|
|
1133
|
+
* in ci — the doctor surfaces that before it does.
|
|
1134
|
+
*
|
|
1135
|
+
* The component filter only narrows the per-component checks; the
|
|
1136
|
+
* cheap project-global checks (store, gitlab, github) always run.
|
|
1137
|
+
*/
|
|
1138
|
+
const doctorProject = async (instance, onlyComponents) => {
|
|
1139
|
+
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
1140
|
+
if (!config) {
|
|
1141
|
+
throw new Error("no catladder config found");
|
|
1142
|
+
}
|
|
1143
|
+
instance.log("🐱 🩺 checking project health — read-only, nothing will be changed");
|
|
1144
|
+
const report = new DoctorReport_1.DoctorReport(instance);
|
|
1145
|
+
await (0, checkStore_1.checkStore)(report);
|
|
1146
|
+
let contexts = [];
|
|
1147
|
+
try {
|
|
1148
|
+
contexts = await (0, getProjectConfig_1.getAllPipelineContexts)(onlyComponents);
|
|
1149
|
+
} catch (e) {
|
|
1150
|
+
report.section("pipeline contexts");
|
|
1151
|
+
report.fail(`could not create pipeline contexts: ${e.message}`, "run: catladder project setup");
|
|
1152
|
+
}
|
|
1153
|
+
if ((0, pipeline_1.getEnabledPipelineTypes)(config).includes("gitlab")) {
|
|
1154
|
+
await (0, checkGitlab_1.checkGitlab)(instance, report, contexts);
|
|
1155
|
+
}
|
|
1156
|
+
await (0, checkCloudRun_1.checkCloudRun)(report, contexts);
|
|
1157
|
+
await (0, checkGithub_1.checkGithub)(report, config);
|
|
1158
|
+
report.summarize();
|
|
1159
|
+
};
|
|
1160
|
+
exports.doctorProject = doctorProject;
|
|
1161
|
+
|
|
1162
|
+
/***/ }),
|
|
1163
|
+
|
|
590
1164
|
/***/ 22661:
|
|
591
1165
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
592
1166
|
|
|
@@ -746,7 +1320,10 @@ const setupAccessTokens = async instance => {
|
|
|
746
1320
|
const {
|
|
747
1321
|
id: projectId
|
|
748
1322
|
} = await (0, gitlab_1.getProjectInfo)(instance);
|
|
749
|
-
|
|
1323
|
+
// all pages: rotated tokens accumulate one (inactive) entry per
|
|
1324
|
+
// rotation, so the active one quickly moves past the first page —
|
|
1325
|
+
// missing it here created a brand-new duplicate token on every setup
|
|
1326
|
+
const projectTokens = await (0, gitlab_1.doGitlabRequestAllPages)(instance, `projects/${projectId}/access_tokens`);
|
|
750
1327
|
const token = projectTokens.find(t => t.name === TOKEN_NAME && t.active === true);
|
|
751
1328
|
const expires_at = (0, date_fns_1.format)((0, date_fns_1.add)(new Date(), {
|
|
752
1329
|
years: 1,
|
|
@@ -963,13 +1540,40 @@ exports.setupAgents = setupAgents;
|
|
|
963
1540
|
Object.defineProperty(exports, "__esModule", ({
|
|
964
1541
|
value: true
|
|
965
1542
|
}));
|
|
966
|
-
exports.setupCloudRun = void 0;
|
|
1543
|
+
exports.setupCloudRun = exports.getCloudRunDeployRoles = exports.getCloudRunRequiredServices = exports.CLOUD_RUN_DEPLOY_SA_NAME = void 0;
|
|
967
1544
|
const pipeline_1 = __nccwpck_require__(60241);
|
|
968
1545
|
const artifactsRegistry_1 = __nccwpck_require__(41624);
|
|
969
1546
|
const enableServices_1 = __nccwpck_require__(96761);
|
|
970
1547
|
const getProjectNumber_1 = __nccwpck_require__(68666);
|
|
971
1548
|
const serviceAccounts_1 = __nccwpck_require__(35611);
|
|
972
1549
|
const updateCatladderStore_1 = __nccwpck_require__(66487);
|
|
1550
|
+
exports.CLOUD_RUN_DEPLOY_SA_NAME = "cl-d";
|
|
1551
|
+
/**
|
|
1552
|
+
* the gcloud services the given deploy config requires.
|
|
1553
|
+
*
|
|
1554
|
+
* Shared with `project doctor`: setup enables them, doctor compares
|
|
1555
|
+
* them against what is actually enabled — config edits after setup
|
|
1556
|
+
* (e.g. adding `cloudSql`) would otherwise drift silently.
|
|
1557
|
+
*/
|
|
1558
|
+
const getCloudRunRequiredServices = config => ["run.googleapis.com", "artifactregistry.googleapis.com", "cloudscheduler.googleapis.com",
|
|
1559
|
+
// for scheduling jobs
|
|
1560
|
+
"cloudresourcemanager.googleapis.com",
|
|
1561
|
+
// only required to get google cloud project number
|
|
1562
|
+
...(config.cloudSql ? ["sqladmin.googleapis.com", "sql-component.googleapis.com"] : [])];
|
|
1563
|
+
exports.getCloudRunRequiredServices = getCloudRunRequiredServices;
|
|
1564
|
+
/**
|
|
1565
|
+
* the IAM roles the deploy service account needs for the given deploy
|
|
1566
|
+
* config. Shared with `project doctor` (same rationale as
|
|
1567
|
+
* {@link getCloudRunRequiredServices}) — the motivating case: a
|
|
1568
|
+
* component gets `cloudSql` after its setup ran, deploys keep working,
|
|
1569
|
+
* and only the review teardown hits the missing `cloudsql.admin`.
|
|
1570
|
+
*/
|
|
1571
|
+
const getCloudRunDeployRoles = config => [
|
|
1572
|
+
// TODO: run.admin is a bit much, would be better to follow https://stackoverflow.com/questions/55788714/deploying-to-cloud-run-with-a-custom-service-account-failed-with-iam-serviceacco
|
|
1573
|
+
"roles/artifactregistry.repoAdmin", "roles/run.admin", "roles/iam.serviceAccountUser", "roles/cloudscheduler.admin",
|
|
1574
|
+
// for scheduling
|
|
1575
|
+
...(config.cloudSql ? ["roles/cloudsql.admin"] : [])];
|
|
1576
|
+
exports.getCloudRunDeployRoles = getCloudRunDeployRoles;
|
|
973
1577
|
const setupCloudRun = async (instance, context) => {
|
|
974
1578
|
var _a, _b;
|
|
975
1579
|
if (!(0, pipeline_1.isOfDeployType)((_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config, "google-cloudrun")) {
|
|
@@ -978,11 +1582,7 @@ const setupCloudRun = async (instance, context) => {
|
|
|
978
1582
|
const config = (_b = context.deploy) === null || _b === void 0 ? void 0 : _b.config;
|
|
979
1583
|
// enable services
|
|
980
1584
|
instance.log("enable required services...");
|
|
981
|
-
await (0, enableServices_1.enableGCloudServices)(
|
|
982
|
-
// for scheduling jobs
|
|
983
|
-
"cloudresourcemanager.googleapis.com",
|
|
984
|
-
// only required to get google cloud project number
|
|
985
|
-
...(config.cloudSql ? ["sqladmin.googleapis.com", "sql-component.googleapis.com"] : [])], config);
|
|
1585
|
+
await (0, enableServices_1.enableGCloudServices)((0, exports.getCloudRunRequiredServices)(config), config);
|
|
986
1586
|
instance.log("upsert artifacts registry...");
|
|
987
1587
|
await (0, artifactsRegistry_1.upsertGcloudArtifactsRegistry)(config);
|
|
988
1588
|
instance.log("upsert deploy service account...");
|
|
@@ -990,11 +1590,8 @@ const setupCloudRun = async (instance, context) => {
|
|
|
990
1590
|
projectId: config.projectId,
|
|
991
1591
|
displayName: "Catladder gcloud deploy",
|
|
992
1592
|
description: "This service account deploys to google cloud",
|
|
993
|
-
name:
|
|
994
|
-
|
|
995
|
-
roles: ["roles/artifactregistry.repoAdmin", "roles/run.admin", "roles/iam.serviceAccountUser", "roles/cloudscheduler.admin",
|
|
996
|
-
// for scheduling
|
|
997
|
-
...(config.cloudSql ? ["roles/cloudsql.admin"] : [])]
|
|
1593
|
+
name: exports.CLOUD_RUN_DEPLOY_SA_NAME,
|
|
1594
|
+
roles: (0, exports.getCloudRunDeployRoles)(config)
|
|
998
1595
|
}, pipeline_1.GCLOUD_DEPLOY_CREDENTIALS_KEY);
|
|
999
1596
|
// the project number is needed at generation time to construct cloud
|
|
1000
1597
|
// run's deterministic urls (<service>-<projectNumber>.<region>.run.app)
|
|
@@ -2064,7 +2661,7 @@ exports.commandKubeStopPortforward = (0, defineCommand_1.defineCommand)({
|
|
|
2064
2661
|
Object.defineProperty(exports, "__esModule", ({
|
|
2065
2662
|
value: true
|
|
2066
2663
|
}));
|
|
2067
|
-
exports.commandStarwars = exports.commandDadjoke = exports.commandSecurityAuditCreate = exports.commandSecurityAuditEvaluate = exports.commandSecurityAuditCiJob = exports.commandRestoreDb = exports.commandMongoDestroyMember = exports.commandMongoPortForward = exports.commandMongoGetShell = exports.commandTriggerCronjobProject = exports.commandDeleteProject = exports.commandPauseProject = exports.commandDeletePods = exports.commandGetShell = exports.commandListPods = exports.commandNamespace = exports.commandSecurityEvaluate = exports.commandProjectRestoreDb = exports.commandCiJobLog = exports.commandCiJobOpen = exports.commandSetup = exports.commandGetMyTotalWorktime = exports.commandRenewToken = exports.commandTriggerCronjobGeneral = exports.commandOpenLogs = exports.commandSecretsSyncGithub = exports.commandSecretsClearBackups = exports.commandConfigSecrets = exports.commandCloudSqlProxy = exports.commandOpenGit = exports.commandOpenEnv = exports.commandPortForward = exports.commandEnvVars = exports.commandKubePortForward = exports.commandKubeGetShell = exports.commandKubeStopPortforward = exports.commandKubeListPods = exports.commandKubeListSecrets = exports.commandKubeListNamespaces = exports.commandKubeCurrentContext = void 0;
|
|
2664
|
+
exports.commandStarwars = exports.commandDadjoke = exports.commandSecurityAuditCreate = exports.commandSecurityAuditEvaluate = exports.commandSecurityAuditCiJob = exports.commandRestoreDb = exports.commandMongoDestroyMember = exports.commandMongoPortForward = exports.commandMongoGetShell = exports.commandTriggerCronjobProject = exports.commandDeleteProject = exports.commandPauseProject = exports.commandDeletePods = exports.commandGetShell = exports.commandListPods = exports.commandNamespace = exports.commandSecurityEvaluate = exports.commandProjectRestoreDb = exports.commandCiJobLog = exports.commandCiJobOpen = exports.commandDoctor = exports.commandSetup = exports.commandGetMyTotalWorktime = exports.commandRenewToken = exports.commandTriggerCronjobGeneral = exports.commandOpenLogs = exports.commandSecretsSyncGithub = exports.commandSecretsClearBackups = exports.commandConfigSecrets = exports.commandCloudSqlProxy = exports.commandOpenGit = exports.commandOpenEnv = exports.commandPortForward = exports.commandEnvVars = exports.commandKubePortForward = exports.commandKubeGetShell = exports.commandKubeStopPortforward = exports.commandKubeListPods = exports.commandKubeListSecrets = exports.commandKubeListNamespaces = exports.commandKubeCurrentContext = void 0;
|
|
2068
2665
|
// General commands
|
|
2069
2666
|
var commandKubeCurrentContext_1 = __nccwpck_require__(70243);
|
|
2070
2667
|
Object.defineProperty(exports, "commandKubeCurrentContext", ({
|
|
@@ -2207,6 +2804,13 @@ Object.defineProperty(exports, "commandSetup", ({
|
|
|
2207
2804
|
return commandSetup_1.commandSetup;
|
|
2208
2805
|
}
|
|
2209
2806
|
}));
|
|
2807
|
+
var commandDoctor_1 = __nccwpck_require__(80248);
|
|
2808
|
+
Object.defineProperty(exports, "commandDoctor", ({
|
|
2809
|
+
enumerable: true,
|
|
2810
|
+
get: function () {
|
|
2811
|
+
return commandDoctor_1.commandDoctor;
|
|
2812
|
+
}
|
|
2813
|
+
}));
|
|
2210
2814
|
var commandGitlabCi_1 = __nccwpck_require__(57076);
|
|
2211
2815
|
Object.defineProperty(exports, "commandCiJobOpen", ({
|
|
2212
2816
|
enumerable: true,
|
|
@@ -2750,6 +3354,38 @@ exports.commandConfigSecrets = (0, defineCommand_1.defineCommand)({
|
|
|
2750
3354
|
|
|
2751
3355
|
/***/ }),
|
|
2752
3356
|
|
|
3357
|
+
/***/ 80248:
|
|
3358
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
3359
|
+
|
|
3360
|
+
"use strict";
|
|
3361
|
+
|
|
3362
|
+
|
|
3363
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
3364
|
+
value: true
|
|
3365
|
+
}));
|
|
3366
|
+
exports.commandDoctor = void 0;
|
|
3367
|
+
const doctor_1 = __nccwpck_require__(96270);
|
|
3368
|
+
const defineCommand_1 = __nccwpck_require__(39489);
|
|
3369
|
+
exports.commandDoctor = (0, defineCommand_1.defineCommand)({
|
|
3370
|
+
name: "project doctor",
|
|
3371
|
+
description: "Checks for drift between the config and the provisioned infrastructure (read-only): service accounts, IAM roles, gitlab tokens, github secrets, store entries.",
|
|
3372
|
+
group: "project",
|
|
3373
|
+
inputs: {
|
|
3374
|
+
component: {
|
|
3375
|
+
type: "string",
|
|
3376
|
+
message: "component name",
|
|
3377
|
+
positional: true,
|
|
3378
|
+
required: false
|
|
3379
|
+
}
|
|
3380
|
+
},
|
|
3381
|
+
execute: async ctx => {
|
|
3382
|
+
const component = await ctx.get("component");
|
|
3383
|
+
await (0, doctor_1.doctorProject)(ctx, component);
|
|
3384
|
+
}
|
|
3385
|
+
});
|
|
3386
|
+
|
|
3387
|
+
/***/ }),
|
|
3388
|
+
|
|
2753
3389
|
/***/ 47838:
|
|
2754
3390
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
2755
3391
|
|
|
@@ -4743,11 +5379,12 @@ exports.MissingInputError = MissingInputError;
|
|
|
4743
5379
|
Object.defineProperty(exports, "__esModule", ({
|
|
4744
5380
|
value: true
|
|
4745
5381
|
}));
|
|
4746
|
-
exports.upsertGcloudArtifactsRegistry = void 0;
|
|
5382
|
+
exports.upsertGcloudArtifactsRegistry = exports.CATLADDER_REGISTRY_NAME = void 0;
|
|
4747
5383
|
const child_process_promise_1 = __nccwpck_require__(51748);
|
|
5384
|
+
exports.CATLADDER_REGISTRY_NAME = "catladder-deploy";
|
|
4748
5385
|
const upsertGcloudArtifactsRegistry = async config => {
|
|
4749
5386
|
try {
|
|
4750
|
-
await (0, child_process_promise_1.exec)(`gcloud artifacts repositories create
|
|
5387
|
+
await (0, child_process_promise_1.exec)(`gcloud artifacts repositories create ${exports.CATLADDER_REGISTRY_NAME} --project="${config.projectId}" --repository-format=docker --location=${config.region}`);
|
|
4751
5388
|
} catch (e) {
|
|
4752
5389
|
// probably already exists
|
|
4753
5390
|
//
|
|
@@ -5006,7 +5643,7 @@ exports.openGoogleCloudDashboard = openGoogleCloudDashboard;
|
|
|
5006
5643
|
|
|
5007
5644
|
/***/ }),
|
|
5008
5645
|
|
|
5009
|
-
/***/
|
|
5646
|
+
/***/ 83798:
|
|
5010
5647
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
5011
5648
|
|
|
5012
5649
|
"use strict";
|
|
@@ -5015,26 +5652,21 @@ exports.openGoogleCloudDashboard = openGoogleCloudDashboard;
|
|
|
5015
5652
|
Object.defineProperty(exports, "__esModule", ({
|
|
5016
5653
|
value: true
|
|
5017
5654
|
}));
|
|
5018
|
-
exports.
|
|
5019
|
-
const child_process_promise_1 = __nccwpck_require__(51748);
|
|
5655
|
+
exports.getGcloudServiceAccountNames = void 0;
|
|
5020
5656
|
const crypto_1 = __nccwpck_require__(76982);
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
const upsertGcloudServiceAccount = async (context, account) => {
|
|
5657
|
+
/**
|
|
5658
|
+
* the deterministic gcloud service account naming used by
|
|
5659
|
+
* `project setup`. Extracted so `project doctor` can compute the
|
|
5660
|
+
* expected identifier of an account without creating anything.
|
|
5661
|
+
*
|
|
5662
|
+
* gcloud limits account ids to 30 chars: the customer/app middle part
|
|
5663
|
+
* (and, if even that is not enough, the env/component suffix) is
|
|
5664
|
+
* replaced by a hash when the full name would not fit.
|
|
5665
|
+
*/
|
|
5666
|
+
const getGcloudServiceAccountNames = (context, account) => {
|
|
5032
5667
|
const {
|
|
5033
5668
|
projectId,
|
|
5034
|
-
name
|
|
5035
|
-
displayName,
|
|
5036
|
-
roles,
|
|
5037
|
-
description
|
|
5669
|
+
name
|
|
5038
5670
|
} = account;
|
|
5039
5671
|
// name has limit of 30
|
|
5040
5672
|
const namePrefix = `${name}`;
|
|
@@ -5055,8 +5687,54 @@ const upsertGcloudServiceAccount = async (context, account) => {
|
|
|
5055
5687
|
nameSuffix = nameSuffixRaw;
|
|
5056
5688
|
}
|
|
5057
5689
|
const fullName = `${namePrefix}-${nameMiddle}-${nameSuffix}`;
|
|
5058
|
-
const fullDisplayName = `${context.fullConfig.customerName}-${context.fullConfig.appName} ${context.env}:${context.name} | ${displayName}`;
|
|
5059
5690
|
const fullIdentifier = `${fullName}@${projectId}.iam.gserviceaccount.com`;
|
|
5691
|
+
return {
|
|
5692
|
+
fullName,
|
|
5693
|
+
fullIdentifier
|
|
5694
|
+
};
|
|
5695
|
+
};
|
|
5696
|
+
exports.getGcloudServiceAccountNames = getGcloudServiceAccountNames;
|
|
5697
|
+
const hashIfNessecary = (str, maxLength) => str.length > maxLength ? hash(str, maxLength) : str;
|
|
5698
|
+
const hash = (str, length) => {
|
|
5699
|
+
return (0, crypto_1.createHmac)("sha256", str).digest("hex").substring(0, length);
|
|
5700
|
+
};
|
|
5701
|
+
|
|
5702
|
+
/***/ }),
|
|
5703
|
+
|
|
5704
|
+
/***/ 35611:
|
|
5705
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
5706
|
+
|
|
5707
|
+
"use strict";
|
|
5708
|
+
|
|
5709
|
+
|
|
5710
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
5711
|
+
value: true
|
|
5712
|
+
}));
|
|
5713
|
+
exports.upsertGcloudServiceAccountAndSaveSecret = exports.accountExists = void 0;
|
|
5714
|
+
const child_process_promise_1 = __nccwpck_require__(51748);
|
|
5715
|
+
const gitlab_1 = __nccwpck_require__(4508);
|
|
5716
|
+
const serviceAccountNames_1 = __nccwpck_require__(83798);
|
|
5717
|
+
const accountExists = async fullIdentifier => {
|
|
5718
|
+
try {
|
|
5719
|
+
await (0, child_process_promise_1.exec)(`gcloud iam service-accounts describe ${fullIdentifier}`);
|
|
5720
|
+
return true;
|
|
5721
|
+
} catch (_a) {
|
|
5722
|
+
return false;
|
|
5723
|
+
}
|
|
5724
|
+
};
|
|
5725
|
+
exports.accountExists = accountExists;
|
|
5726
|
+
const upsertGcloudServiceAccount = async (context, account) => {
|
|
5727
|
+
const {
|
|
5728
|
+
projectId,
|
|
5729
|
+
displayName,
|
|
5730
|
+
roles,
|
|
5731
|
+
description
|
|
5732
|
+
} = account;
|
|
5733
|
+
const {
|
|
5734
|
+
fullName,
|
|
5735
|
+
fullIdentifier
|
|
5736
|
+
} = (0, serviceAccountNames_1.getGcloudServiceAccountNames)(context, account);
|
|
5737
|
+
const fullDisplayName = `${context.fullConfig.customerName}-${context.fullConfig.appName} ${context.env}:${context.name} | ${displayName}`;
|
|
5060
5738
|
const existing = await (0, exports.accountExists)(fullIdentifier);
|
|
5061
5739
|
if (!existing) {
|
|
5062
5740
|
await (0, child_process_promise_1.exec)(`gcloud iam service-accounts create ${fullName} --display-name="${fullDisplayName}" --project="${projectId}" --description="${description}"`);
|
|
@@ -5084,10 +5762,6 @@ const upsertGcloudServiceAccountAndSaveSecret = async (instance, context, accoun
|
|
|
5084
5762
|
instance.log("done!");
|
|
5085
5763
|
};
|
|
5086
5764
|
exports.upsertGcloudServiceAccountAndSaveSecret = upsertGcloudServiceAccountAndSaveSecret;
|
|
5087
|
-
const hashIfNessecary = (str, maxLength) => str.length > maxLength ? hash(str, maxLength) : str;
|
|
5088
|
-
const hash = (str, length) => {
|
|
5089
|
-
return (0, crypto_1.createHmac)("sha256", str).digest("hex").substring(0, length);
|
|
5090
|
-
};
|
|
5091
5765
|
|
|
5092
5766
|
/***/ }),
|
|
5093
5767
|
|
|
@@ -5665,6 +6339,40 @@ exports.connectToCluster = connectToCluster;
|
|
|
5665
6339
|
|
|
5666
6340
|
/***/ }),
|
|
5667
6341
|
|
|
6342
|
+
/***/ 5092:
|
|
6343
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
6344
|
+
|
|
6345
|
+
"use strict";
|
|
6346
|
+
|
|
6347
|
+
|
|
6348
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6349
|
+
value: true
|
|
6350
|
+
}));
|
|
6351
|
+
exports.mapWithConcurrency = void 0;
|
|
6352
|
+
/**
|
|
6353
|
+
* maps over items with at most `limit` calls in flight, preserving the
|
|
6354
|
+
* input order in the result (unlike reporting-as-you-go, this lets
|
|
6355
|
+
* callers run slow per-item lookups in parallel and still log the
|
|
6356
|
+
* outcomes in a stable order)
|
|
6357
|
+
*/
|
|
6358
|
+
const mapWithConcurrency = async (items, limit, fn) => {
|
|
6359
|
+
const results = new Array(items.length);
|
|
6360
|
+
let next = 0;
|
|
6361
|
+
const workers = Array.from({
|
|
6362
|
+
length: Math.max(1, Math.min(limit, items.length))
|
|
6363
|
+
}, async () => {
|
|
6364
|
+
while (next < items.length) {
|
|
6365
|
+
const index = next++;
|
|
6366
|
+
results[index] = await fn(items[index], index);
|
|
6367
|
+
}
|
|
6368
|
+
});
|
|
6369
|
+
await Promise.all(workers);
|
|
6370
|
+
return results;
|
|
6371
|
+
};
|
|
6372
|
+
exports.mapWithConcurrency = mapWithConcurrency;
|
|
6373
|
+
|
|
6374
|
+
/***/ }),
|
|
6375
|
+
|
|
5668
6376
|
/***/ 82805:
|
|
5669
6377
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
5670
6378
|
|
|
@@ -5778,7 +6486,7 @@ exports["default"] = async () => {
|
|
|
5778
6486
|
Object.defineProperty(exports, "__esModule", ({
|
|
5779
6487
|
value: true
|
|
5780
6488
|
}));
|
|
5781
|
-
exports.ensureGithubEnvironment = exports.setGithubVariable = exports.setGithubSecret = exports.getGithubRepoFromRemote = exports.isGhAuthenticated = void 0;
|
|
6489
|
+
exports.ensureGithubEnvironment = exports.setGithubVariable = exports.setGithubSecret = exports.listGithubVariableNames = exports.listGithubSecretNames = exports.listGithubEnvironments = exports.getGithubRepoFromRemote = exports.isGhAuthenticated = void 0;
|
|
5782
6490
|
const child_process_1 = __nccwpck_require__(35317);
|
|
5783
6491
|
const util_1 = __nccwpck_require__(39023);
|
|
5784
6492
|
const execFile = (0, util_1.promisify)(child_process_1.execFile);
|
|
@@ -5811,6 +6519,31 @@ const getGithubRepoFromRemote = async remoteName => {
|
|
|
5811
6519
|
}
|
|
5812
6520
|
};
|
|
5813
6521
|
exports.getGithubRepoFromRemote = getGithubRepoFromRemote;
|
|
6522
|
+
/**
|
|
6523
|
+
* runs a paginated `gh api` query and returns the jq-extracted lines
|
|
6524
|
+
* (one value per line, e.g. names)
|
|
6525
|
+
*/
|
|
6526
|
+
const ghApiLines = async (path, jq) => {
|
|
6527
|
+
const {
|
|
6528
|
+
stdout
|
|
6529
|
+
} = await execFile("gh", ["api", "--paginate", path, "--jq", jq], {
|
|
6530
|
+
maxBuffer: 10 * 1024 * 1024
|
|
6531
|
+
});
|
|
6532
|
+
return stdout.split("\n").map(line => line.trim()).filter(Boolean);
|
|
6533
|
+
};
|
|
6534
|
+
/** names of all deployment environments of the repository */
|
|
6535
|
+
const listGithubEnvironments = repo => ghApiLines(`repos/${repo}/environments?per_page=100`, ".environments[].name");
|
|
6536
|
+
exports.listGithubEnvironments = listGithubEnvironments;
|
|
6537
|
+
/**
|
|
6538
|
+
* names of the actions secrets — of an environment, or of the repo
|
|
6539
|
+
* level when no environment is given. Github secrets are write-only:
|
|
6540
|
+
* names are all that can ever be inspected.
|
|
6541
|
+
*/
|
|
6542
|
+
const listGithubSecretNames = (repo, environment) => ghApiLines(environment ? `repos/${repo}/environments/${encodeURIComponent(environment)}/secrets?per_page=100` : `repos/${repo}/actions/secrets?per_page=100`, ".secrets[].name");
|
|
6543
|
+
exports.listGithubSecretNames = listGithubSecretNames;
|
|
6544
|
+
/** names of the actions variables (environment or repo level) */
|
|
6545
|
+
const listGithubVariableNames = (repo, environment) => ghApiLines(environment ? `repos/${repo}/environments/${encodeURIComponent(environment)}/variables?per_page=100` : `repos/${repo}/actions/variables?per_page=100`, ".variables[].name");
|
|
6546
|
+
exports.listGithubVariableNames = listGithubVariableNames;
|
|
5814
6547
|
const ghSetViaStdin = (kind, repo, name, value, environment) => new Promise((resolve, reject) => {
|
|
5815
6548
|
var _a, _b;
|
|
5816
6549
|
const child = (0, child_process_1.spawn)("gh", [kind, "set", name, "--repo", repo, ...(environment ? ["--env", environment] : [])], {
|
|
@@ -5866,7 +6599,7 @@ var __importDefault = this && this.__importDefault || function (mod) {
|
|
|
5866
6599
|
Object.defineProperty(exports, "__esModule", ({
|
|
5867
6600
|
value: true
|
|
5868
6601
|
}));
|
|
5869
|
-
exports.upsertAllVariables = exports.clearBackups = exports.getVariableValueByRawName = exports.getAllVariables = exports.getProjectInfo = exports.doGitlabRequest = exports.getGitlabToken = exports.setupGitlabToken = exports.hasGitlabToken = void 0;
|
|
6602
|
+
exports.upsertAllVariables = exports.clearBackups = exports.getVariableValueByRawName = exports.getAllVariables = exports.getProjectInfo = exports.doGitlabRequestAllPages = exports.doGitlabRequest = exports.getGitlabToken = exports.setupGitlabToken = exports.hasGitlabToken = void 0;
|
|
5870
6603
|
const pipeline_1 = __nccwpck_require__(60241);
|
|
5871
6604
|
const lodash_es_1 = __nccwpck_require__(64284);
|
|
5872
6605
|
const memoizee_1 = __importDefault(__nccwpck_require__(57009));
|
|
@@ -5937,6 +6670,24 @@ const doGitlabRequest = async (io, path, data = undefined, method = "GET") => {
|
|
|
5937
6670
|
throw new Error(`Could not send request to gitlab api ${path}: ${result.status} "${result.statusText}".\nResponse: ${JSON.stringify(await result.json(), null, 2)}`);
|
|
5938
6671
|
};
|
|
5939
6672
|
exports.doGitlabRequest = doGitlabRequest;
|
|
6673
|
+
/**
|
|
6674
|
+
* GET a list endpoint across ALL pages (gitlab returns 20 items per
|
|
6675
|
+
* page by default — long-lived projects easily exceed that, e.g.
|
|
6676
|
+
* rotated access tokens accumulate one entry per rotation)
|
|
6677
|
+
*/
|
|
6678
|
+
const doGitlabRequestAllPages = async (io, path) => {
|
|
6679
|
+
const PER_PAGE = 100;
|
|
6680
|
+
const separator = path.includes("?") ? "&" : "?";
|
|
6681
|
+
const all = [];
|
|
6682
|
+
for (let page = 1;; page++) {
|
|
6683
|
+
const items = await (0, exports.doGitlabRequest)(io, `${path}${separator}per_page=${PER_PAGE}&page=${page}`);
|
|
6684
|
+
if (!(items === null || items === void 0 ? void 0 : items.length)) break;
|
|
6685
|
+
all.push(...items);
|
|
6686
|
+
if (items.length < PER_PAGE) break;
|
|
6687
|
+
}
|
|
6688
|
+
return all;
|
|
6689
|
+
};
|
|
6690
|
+
exports.doGitlabRequestAllPages = doGitlabRequestAllPages;
|
|
5940
6691
|
const getProjectInfo = async io => {
|
|
5941
6692
|
const {
|
|
5942
6693
|
gitRemotePath
|
|
@@ -10640,7 +11391,7 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
10640
11391
|
value: true
|
|
10641
11392
|
}));
|
|
10642
11393
|
exports.DOCKER_REGISTRY = exports.PIPELINE_IMAGE_TAG = void 0;
|
|
10643
|
-
exports.PIPELINE_IMAGE_TAG = "next-
|
|
11394
|
+
exports.PIPELINE_IMAGE_TAG = "next-51dc9c2b" || 0;
|
|
10644
11395
|
exports.DOCKER_REGISTRY = "git.panter.ch:5001/catladder/catladder" || 0;
|
|
10645
11396
|
|
|
10646
11397
|
/***/ }),
|
|
@@ -12953,6 +13704,18 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
|
|
|
12953
13704
|
DEPLOY_CLOUD_RUN_PROJECT_ID: deployConfigRaw ? deployConfigRaw.projectId : undefined,
|
|
12954
13705
|
DEPLOY_CLOUD_RUN_REGION: deployConfigRaw ? deployConfigRaw.region : undefined
|
|
12955
13706
|
};
|
|
13707
|
+
},
|
|
13708
|
+
verifyJobSetupScript: context => {
|
|
13709
|
+
var _a;
|
|
13710
|
+
const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
|
|
13711
|
+
const service = deployConfig === null || deployConfig === void 0 ? void 0 : deployConfig.service;
|
|
13712
|
+
const serviceConfig = typeof service === "object" ? service : undefined;
|
|
13713
|
+
if ((serviceConfig === null || serviceConfig === void 0 ? void 0 : serviceConfig.allowUnauthenticated) !== false) {
|
|
13714
|
+
return [];
|
|
13715
|
+
}
|
|
13716
|
+
// the service requires IAM auth: provide application default credentials
|
|
13717
|
+
// so the verify command can fetch identity tokens for the deployed service
|
|
13718
|
+
return (0, gitlab_1.collapseableSection)("verifygcloudauth", "Setup google application credentials")([`echo "$${exports.GCLOUD_DEPLOY_CREDENTIALS_KEY}" > "$CI_PROJECT_DIR/.gcloud-sa.json"`, `export GOOGLE_APPLICATION_CREDENTIALS="$CI_PROJECT_DIR/.gcloud-sa.json"`]);
|
|
12956
13719
|
}
|
|
12957
13720
|
};
|
|
12958
13721
|
|
|
@@ -14076,6 +14839,7 @@ __exportStar(__nccwpck_require__(20623), exports);
|
|
|
14076
14839
|
__exportStar(__nccwpck_require__(38045), exports);
|
|
14077
14840
|
__exportStar(__nccwpck_require__(51398), exports);
|
|
14078
14841
|
__exportStar(__nccwpck_require__(88025), exports);
|
|
14842
|
+
__exportStar(__nccwpck_require__(39871), exports);
|
|
14079
14843
|
__exportStar(__nccwpck_require__(45585), exports);
|
|
14080
14844
|
__exportStar(__nccwpck_require__(47666), exports);
|
|
14081
14845
|
__exportStar(__nccwpck_require__(60250), exports);
|
|
@@ -14705,6 +15469,7 @@ exports.createJobsForComponentContext = void 0;
|
|
|
14705
15469
|
const build_1 = __nccwpck_require__(51398);
|
|
14706
15470
|
const deploy_1 = __nccwpck_require__(88025);
|
|
14707
15471
|
const jobs_1 = __nccwpck_require__(41507);
|
|
15472
|
+
const createVerifyJobs_1 = __nccwpck_require__(69134);
|
|
14708
15473
|
const injectDefaultVarsInCustomJobs = (context, jobs) => jobs.map(({
|
|
14709
15474
|
variables,
|
|
14710
15475
|
...job
|
|
@@ -14726,9 +15491,9 @@ const getCustomJobs = context => {
|
|
|
14726
15491
|
return injectDefaultVarsInCustomJobs(context, rawJobs);
|
|
14727
15492
|
};
|
|
14728
15493
|
const createJobsForComponentContext = async context => {
|
|
14729
|
-
const [buildJobs, deployJobs] = await Promise.all([context.build.type !== "disabled" ? build_1.BUILD_TYPES[context.build.buildType].jobs(context) : [], context.componentConfig.deploy !== false ? deploy_1.DEPLOY_TYPES[context.componentConfig.deploy.type].jobs(context) : []]);
|
|
15494
|
+
const [buildJobs, deployJobs, verifyJobs] = await Promise.all([context.build.type !== "disabled" ? build_1.BUILD_TYPES[context.build.buildType].jobs(context) : [], context.componentConfig.deploy !== false ? deploy_1.DEPLOY_TYPES[context.componentConfig.deploy.type].jobs(context) : [], (0, createVerifyJobs_1.createVerifyJobs)(context)]);
|
|
14730
15495
|
const customJobs = getCustomJobs(context);
|
|
14731
|
-
return [...buildJobs, ...deployJobs, ...customJobs];
|
|
15496
|
+
return [...buildJobs, ...deployJobs, ...verifyJobs, ...customJobs];
|
|
14732
15497
|
};
|
|
14733
15498
|
exports.createJobsForComponentContext = createJobsForComponentContext;
|
|
14734
15499
|
|
|
@@ -15872,6 +16637,121 @@ exports.resolveReferencesOnce = resolveReferencesOnce;
|
|
|
15872
16637
|
|
|
15873
16638
|
/***/ }),
|
|
15874
16639
|
|
|
16640
|
+
/***/ 69134:
|
|
16641
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
16642
|
+
|
|
16643
|
+
"use strict";
|
|
16644
|
+
|
|
16645
|
+
|
|
16646
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
16647
|
+
value: true
|
|
16648
|
+
}));
|
|
16649
|
+
exports.createVerifyJobs = exports.VERIFY_JOB_NAME = void 0;
|
|
16650
|
+
const createArtifactsConfig_1 = __nccwpck_require__(43983);
|
|
16651
|
+
const createJobCache_1 = __nccwpck_require__(65644);
|
|
16652
|
+
const cache_1 = __nccwpck_require__(34189);
|
|
16653
|
+
const constants_1 = __nccwpck_require__(37878);
|
|
16654
|
+
const yarn_1 = __nccwpck_require__(78897);
|
|
16655
|
+
const deploy_1 = __nccwpck_require__(88025);
|
|
16656
|
+
const runner_1 = __nccwpck_require__(92348);
|
|
16657
|
+
const utils_1 = __nccwpck_require__(20595);
|
|
16658
|
+
exports.VERIFY_JOB_NAME = "🔍 verify";
|
|
16659
|
+
const createVerifyJobs = async context => {
|
|
16660
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
16661
|
+
const verifyConfig = context.componentConfig.verify;
|
|
16662
|
+
if (!verifyConfig) {
|
|
16663
|
+
return [];
|
|
16664
|
+
}
|
|
16665
|
+
const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
|
|
16666
|
+
if (!deployConfig) {
|
|
16667
|
+
// nothing is deployed, so there is nothing to verify
|
|
16668
|
+
return [];
|
|
16669
|
+
}
|
|
16670
|
+
const isNodeBuild = context.build.type !== "disabled" && context.build.buildType === "node";
|
|
16671
|
+
const [yarnInstall, nodeCache] = isNodeBuild ? await Promise.all([(0, yarn_1.getYarnInstall)(context), (0, cache_1.getNodeCache)(context, "pull")]) : [null, null];
|
|
16672
|
+
const setupScript = (_d = (_c = (_b = deploy_1.DEPLOY_TYPES[deployConfig.type]).verifyJobSetupScript) === null || _c === void 0 ? void 0 : _c.call(_b, context)) !== null && _d !== void 0 ? _d : [];
|
|
16673
|
+
return [{
|
|
16674
|
+
name: exports.VERIFY_JOB_NAME,
|
|
16675
|
+
stage: "verify",
|
|
16676
|
+
envMode: "stagePerEnv",
|
|
16677
|
+
requires: [
|
|
16678
|
+
// wait for this component's own deploy
|
|
16679
|
+
{
|
|
16680
|
+
capability: "deployment",
|
|
16681
|
+
artifacts: false
|
|
16682
|
+
},
|
|
16683
|
+
// ...and for the deploys of the components listed in waitFor
|
|
16684
|
+
...((_e = verifyConfig.waitFor) !== null && _e !== void 0 ? _e : []).map(componentName => ({
|
|
16685
|
+
capability: "deployment",
|
|
16686
|
+
from: {
|
|
16687
|
+
component: componentName
|
|
16688
|
+
},
|
|
16689
|
+
artifacts: false,
|
|
16690
|
+
strict: true
|
|
16691
|
+
}))],
|
|
16692
|
+
image: (_f = verifyConfig.jobImage) !== null && _f !== void 0 ? _f : (0, runner_1.getRunnerImage)("jobs-testing-chrome"),
|
|
16693
|
+
cache: nodeCache ? (0, createJobCache_1.createJobCacheFromCacheConfigs)(context, nodeCache) : undefined,
|
|
16694
|
+
variables: {
|
|
16695
|
+
...context.environment.envVars
|
|
16696
|
+
},
|
|
16697
|
+
runnerVariables: {
|
|
16698
|
+
...constants_1.NODE_RUNNER_BUILD_VARIABLES,
|
|
16699
|
+
...((_g = verifyConfig.runnerVariables) !== null && _g !== void 0 ? _g : {})
|
|
16700
|
+
},
|
|
16701
|
+
script: [...setupScript, ...(yarnInstall ? (0, yarn_1.ensureNodeVersion)(context) : []), `cd ${context.build.dir}`, ...(yarnInstall !== null && yarnInstall !== void 0 ? yarnInstall : []), ...(0, utils_1.ensureArray)(verifyConfig.command)],
|
|
16702
|
+
allow_failure: verifyConfig.allowFailure,
|
|
16703
|
+
...(0, createArtifactsConfig_1.createArtifactsConfig)(context.build.dir, verifyConfig.artifactsReports, verifyConfig.artifacts)
|
|
16704
|
+
}];
|
|
16705
|
+
};
|
|
16706
|
+
exports.createVerifyJobs = createVerifyJobs;
|
|
16707
|
+
|
|
16708
|
+
/***/ }),
|
|
16709
|
+
|
|
16710
|
+
/***/ 39871:
|
|
16711
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
16712
|
+
|
|
16713
|
+
"use strict";
|
|
16714
|
+
|
|
16715
|
+
|
|
16716
|
+
var __createBinding = this && this.__createBinding || (Object.create ? function (o, m, k, k2) {
|
|
16717
|
+
if (k2 === undefined) k2 = k;
|
|
16718
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16719
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16720
|
+
desc = {
|
|
16721
|
+
enumerable: true,
|
|
16722
|
+
get: function () {
|
|
16723
|
+
return m[k];
|
|
16724
|
+
}
|
|
16725
|
+
};
|
|
16726
|
+
}
|
|
16727
|
+
Object.defineProperty(o, k2, desc);
|
|
16728
|
+
} : function (o, m, k, k2) {
|
|
16729
|
+
if (k2 === undefined) k2 = k;
|
|
16730
|
+
o[k2] = m[k];
|
|
16731
|
+
});
|
|
16732
|
+
var __exportStar = this && this.__exportStar || function (m, exports) {
|
|
16733
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16734
|
+
};
|
|
16735
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
16736
|
+
value: true
|
|
16737
|
+
}));
|
|
16738
|
+
__exportStar(__nccwpck_require__(99318), exports);
|
|
16739
|
+
__exportStar(__nccwpck_require__(69134), exports);
|
|
16740
|
+
|
|
16741
|
+
/***/ }),
|
|
16742
|
+
|
|
16743
|
+
/***/ 99318:
|
|
16744
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
16745
|
+
|
|
16746
|
+
"use strict";
|
|
16747
|
+
|
|
16748
|
+
|
|
16749
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
16750
|
+
value: true
|
|
16751
|
+
}));
|
|
16752
|
+
|
|
16753
|
+
/***/ }),
|
|
16754
|
+
|
|
15875
16755
|
/***/ 29879:
|
|
15876
16756
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
15877
16757
|
|