@biffo/cli 0.41.0 → 0.41.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core.version +1 -1
- package/dist/index.js +175 -82
- package/package.json +1 -1
package/core.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.41.
|
|
1
|
+
0.41.2
|
package/dist/index.js
CHANGED
|
@@ -599,9 +599,19 @@ var GitHubAdapter = class {
|
|
|
599
599
|
async createEmptyRepo(org, repo, description) {
|
|
600
600
|
try {
|
|
601
601
|
const { data: existing } = await this.octokit.repos.get({ owner: org, repo });
|
|
602
|
-
|
|
602
|
+
if (await this.repoHasCommits(org, repo)) {
|
|
603
|
+
throw new Error(
|
|
604
|
+
`Repository ${org}/${repo} already exists and is not empty.
|
|
605
|
+
Biffo will not push the sibling skeleton over a repo that has content.
|
|
606
|
+
If this repo is a half-finished Biffo sibling you want to redo, delete it
|
|
607
|
+
(gh repo delete ${org}/${repo}) and re-run. If it is unrelated, choose a
|
|
608
|
+
different sibling name.`
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
log.info(`Repository ${org}/${repo} already exists and is empty \u2014 adopting it`);
|
|
603
612
|
return existing.clone_url;
|
|
604
613
|
} catch (err) {
|
|
614
|
+
if (err instanceof Error && !("status" in err)) throw err;
|
|
605
615
|
if (err.status !== 404) throw err;
|
|
606
616
|
}
|
|
607
617
|
log.info(`Creating repository ${org}/${repo}...`);
|
|
@@ -625,6 +635,27 @@ var GitHubAdapter = class {
|
|
|
625
635
|
log.success(`Repository created: ${data.html_url}`);
|
|
626
636
|
return data.clone_url;
|
|
627
637
|
}
|
|
638
|
+
/**
|
|
639
|
+
* Does `org/repo` have any commits on any branch?
|
|
640
|
+
*
|
|
641
|
+
* `repos.get`'s `size` is unreliable for this — it is in KB and reports 0 for
|
|
642
|
+
* a freshly-pushed small repo. GitHub answers the question directly instead:
|
|
643
|
+
* listing commits on a repo with no commits returns 409 ("Git Repository is
|
|
644
|
+
* empty"). A 404 means the repo itself is gone, which is also "no commits".
|
|
645
|
+
*
|
|
646
|
+
* Used to decide whether an existing repo is safe to adopt (issue #316) and
|
|
647
|
+
* whether a skeleton push has already happened.
|
|
648
|
+
*/
|
|
649
|
+
async repoHasCommits(org, repo) {
|
|
650
|
+
try {
|
|
651
|
+
const { data } = await this.octokit.repos.listCommits({ owner: org, repo, per_page: 1 });
|
|
652
|
+
return data.length > 0;
|
|
653
|
+
} catch (err) {
|
|
654
|
+
const status = err.status;
|
|
655
|
+
if (status === 409 || status === 404) return false;
|
|
656
|
+
throw err;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
628
659
|
async deleteRepo(org, repo) {
|
|
629
660
|
try {
|
|
630
661
|
await this.octokit.repos.get({ owner: org, repo });
|
|
@@ -2197,6 +2228,13 @@ import {
|
|
|
2197
2228
|
} from "fs";
|
|
2198
2229
|
import { homedir } from "os";
|
|
2199
2230
|
import { join as join9 } from "path";
|
|
2231
|
+
var LEGACY_STEP_ALIASES = {
|
|
2232
|
+
github_config: ["github_branches", "github_instance_files", "github_settings"]
|
|
2233
|
+
};
|
|
2234
|
+
function hasCompleted(session, step) {
|
|
2235
|
+
if (session.completedSteps.includes(step)) return true;
|
|
2236
|
+
return session.completedSteps.some((done) => LEGACY_STEP_ALIASES[done]?.includes(step) ?? false);
|
|
2237
|
+
}
|
|
2200
2238
|
function sessionsDir() {
|
|
2201
2239
|
return process.env["BIFFO_SESSIONS_DIR"] ?? join9(homedir(), ".biffo", "sessions");
|
|
2202
2240
|
}
|
|
@@ -2232,8 +2270,18 @@ function saveSession(session) {
|
|
|
2232
2270
|
const dir = sessionsDir();
|
|
2233
2271
|
if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
|
|
2234
2272
|
const name = session.config.project?.name ?? "unknown";
|
|
2273
|
+
const prior = loadSession(name);
|
|
2274
|
+
if (prior) {
|
|
2275
|
+
for (const step of prior.completedSteps) {
|
|
2276
|
+
if (!session.completedSteps.includes(step)) session.completedSteps.push(step);
|
|
2277
|
+
}
|
|
2278
|
+
session.outputs = { ...prior.outputs, ...definedOnly(session.outputs) };
|
|
2279
|
+
}
|
|
2235
2280
|
writeFileSync4(sessionPath(name), JSON.stringify(session, null, 2));
|
|
2236
2281
|
}
|
|
2282
|
+
function definedOnly(value) {
|
|
2283
|
+
return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== void 0));
|
|
2284
|
+
}
|
|
2237
2285
|
function markStepComplete(session, step) {
|
|
2238
2286
|
if (!session.completedSteps.includes(step)) {
|
|
2239
2287
|
session.completedSteps.push(step);
|
|
@@ -3554,64 +3602,29 @@ var SiblingConfigSchema = z4.object({
|
|
|
3554
3602
|
}
|
|
3555
3603
|
});
|
|
3556
3604
|
|
|
3557
|
-
// src/commands/sibling-create.ts
|
|
3558
|
-
import { cpSync as cpSync2, existsSync as existsSync14, mkdirSync as mkdirSync6, mkdtempSync as mkdtempSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "fs";
|
|
3559
|
-
import { tmpdir as tmpdir4 } from "os";
|
|
3560
|
-
import { dirname as dirname6, join as join16, resolve as resolve9 } from "path";
|
|
3561
|
-
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3562
|
-
import chalk11 from "chalk";
|
|
3563
|
-
import { Command as Command11 } from "commander";
|
|
3564
|
-
|
|
3565
|
-
// src/lib/skeleton-dotfiles.ts
|
|
3566
|
-
import { readdirSync as readdirSync7, renameSync } from "fs";
|
|
3567
|
-
import { join as join14 } from "path";
|
|
3568
|
-
var PACKAGED_GITIGNORE = "_gitignore";
|
|
3569
|
-
var REAL_GITIGNORE = ".gitignore";
|
|
3570
|
-
function restorePackagedDotfiles(dir) {
|
|
3571
|
-
const restored = [];
|
|
3572
|
-
for (const entry of readdirSync7(dir, { withFileTypes: true })) {
|
|
3573
|
-
const full = join14(dir, entry.name);
|
|
3574
|
-
if (entry.isDirectory()) {
|
|
3575
|
-
restored.push(...restorePackagedDotfiles(full));
|
|
3576
|
-
} else if (entry.name === PACKAGED_GITIGNORE) {
|
|
3577
|
-
const target = join14(dir, REAL_GITIGNORE);
|
|
3578
|
-
renameSync(full, target);
|
|
3579
|
-
restored.push(target);
|
|
3580
|
-
}
|
|
3581
|
-
}
|
|
3582
|
-
return restored;
|
|
3583
|
-
}
|
|
3584
|
-
|
|
3585
3605
|
// src/lib/sibling-session.ts
|
|
3586
3606
|
import {
|
|
3587
3607
|
existsSync as existsSync13,
|
|
3588
3608
|
mkdirSync as mkdirSync5,
|
|
3589
|
-
readdirSync as
|
|
3609
|
+
readdirSync as readdirSync7,
|
|
3590
3610
|
readFileSync as readFileSync10,
|
|
3591
3611
|
rmSync as rmSync5,
|
|
3592
3612
|
statSync as statSync4,
|
|
3593
3613
|
writeFileSync as writeFileSync5
|
|
3594
3614
|
} from "fs";
|
|
3595
3615
|
import { homedir as homedir3 } from "os";
|
|
3596
|
-
import { join as
|
|
3616
|
+
import { join as join14 } from "path";
|
|
3597
3617
|
function sessionsDir2() {
|
|
3598
|
-
return process.env["BIFFO_SIBLING_SESSIONS_DIR"] ??
|
|
3618
|
+
return process.env["BIFFO_SIBLING_SESSIONS_DIR"] ?? join14(homedir3(), ".biffo", "sibling-sessions");
|
|
3599
3619
|
}
|
|
3600
3620
|
function sessionPath2(projectName) {
|
|
3601
|
-
return
|
|
3621
|
+
return join14(sessionsDir2(), `${projectName}.json`);
|
|
3602
3622
|
}
|
|
3603
|
-
function
|
|
3604
|
-
const
|
|
3605
|
-
if (!existsSync13(
|
|
3606
|
-
const files = readdirSync8(dir).filter((f) => f.endsWith(".json"));
|
|
3607
|
-
if (files.length === 0) return null;
|
|
3608
|
-
const sorted = files.map((f) => {
|
|
3609
|
-
const fullPath = join15(dir, f);
|
|
3610
|
-
const mtime = existsSync13(fullPath) ? statSync4(fullPath).mtimeMs : -1;
|
|
3611
|
-
return { f, mtime };
|
|
3612
|
-
}).sort((a, b) => b.mtime - a.mtime);
|
|
3623
|
+
function loadSiblingSession(projectName) {
|
|
3624
|
+
const path = sessionPath2(projectName);
|
|
3625
|
+
if (!existsSync13(path)) return null;
|
|
3613
3626
|
try {
|
|
3614
|
-
return JSON.parse(readFileSync10(
|
|
3627
|
+
return JSON.parse(readFileSync10(path, "utf8"));
|
|
3615
3628
|
} catch {
|
|
3616
3629
|
return null;
|
|
3617
3630
|
}
|
|
@@ -3620,8 +3633,18 @@ function saveSiblingSession(session) {
|
|
|
3620
3633
|
const dir = sessionsDir2();
|
|
3621
3634
|
if (!existsSync13(dir)) mkdirSync5(dir, { recursive: true });
|
|
3622
3635
|
const name = session.config.project?.name ?? "unknown";
|
|
3636
|
+
const prior = loadSiblingSession(name);
|
|
3637
|
+
if (prior) {
|
|
3638
|
+
for (const step of prior.completedSteps) {
|
|
3639
|
+
if (!session.completedSteps.includes(step)) session.completedSteps.push(step);
|
|
3640
|
+
}
|
|
3641
|
+
session.outputs = { ...prior.outputs, ...definedOnly2(session.outputs) };
|
|
3642
|
+
}
|
|
3623
3643
|
writeFileSync5(sessionPath2(name), JSON.stringify(session, null, 2));
|
|
3624
3644
|
}
|
|
3645
|
+
function definedOnly2(value) {
|
|
3646
|
+
return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== void 0));
|
|
3647
|
+
}
|
|
3625
3648
|
function markSiblingStepComplete(session, step) {
|
|
3626
3649
|
if (!session.completedSteps.includes(step)) {
|
|
3627
3650
|
session.completedSteps.push(step);
|
|
@@ -3633,6 +3656,34 @@ function deleteSiblingSession(projectName) {
|
|
|
3633
3656
|
if (existsSync13(path)) rmSync5(path);
|
|
3634
3657
|
}
|
|
3635
3658
|
|
|
3659
|
+
// src/commands/sibling-create.ts
|
|
3660
|
+
import { cpSync as cpSync2, existsSync as existsSync14, mkdirSync as mkdirSync6, mkdtempSync as mkdtempSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "fs";
|
|
3661
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
3662
|
+
import { dirname as dirname6, join as join16, resolve as resolve9 } from "path";
|
|
3663
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3664
|
+
import chalk11 from "chalk";
|
|
3665
|
+
import { Command as Command11 } from "commander";
|
|
3666
|
+
|
|
3667
|
+
// src/lib/skeleton-dotfiles.ts
|
|
3668
|
+
import { readdirSync as readdirSync8, renameSync } from "fs";
|
|
3669
|
+
import { join as join15 } from "path";
|
|
3670
|
+
var PACKAGED_GITIGNORE = "_gitignore";
|
|
3671
|
+
var REAL_GITIGNORE = ".gitignore";
|
|
3672
|
+
function restorePackagedDotfiles(dir) {
|
|
3673
|
+
const restored = [];
|
|
3674
|
+
for (const entry of readdirSync8(dir, { withFileTypes: true })) {
|
|
3675
|
+
const full = join15(dir, entry.name);
|
|
3676
|
+
if (entry.isDirectory()) {
|
|
3677
|
+
restored.push(...restorePackagedDotfiles(full));
|
|
3678
|
+
} else if (entry.name === PACKAGED_GITIGNORE) {
|
|
3679
|
+
const target = join15(dir, REAL_GITIGNORE);
|
|
3680
|
+
renameSync(full, target);
|
|
3681
|
+
restored.push(target);
|
|
3682
|
+
}
|
|
3683
|
+
}
|
|
3684
|
+
return restored;
|
|
3685
|
+
}
|
|
3686
|
+
|
|
3636
3687
|
// src/commands/sibling-create.ts
|
|
3637
3688
|
var siblingCreateCommand = new Command11("create").description(
|
|
3638
3689
|
"Create a standalone sibling app repository from the Biffo sibling template (ADR-0007)"
|
|
@@ -3675,8 +3726,8 @@ async function runSiblingCreateCommand(name, options) {
|
|
|
3675
3726
|
}
|
|
3676
3727
|
let session = null;
|
|
3677
3728
|
if (!options.fresh) {
|
|
3678
|
-
const saved =
|
|
3679
|
-
if (saved
|
|
3729
|
+
const saved = loadSiblingSession(name);
|
|
3730
|
+
if (saved) {
|
|
3680
3731
|
session = saved;
|
|
3681
3732
|
console.log(
|
|
3682
3733
|
chalk11.dim(
|
|
@@ -3687,6 +3738,7 @@ async function runSiblingCreateCommand(name, options) {
|
|
|
3687
3738
|
}
|
|
3688
3739
|
}
|
|
3689
3740
|
if (!session) {
|
|
3741
|
+
deleteSiblingSession(name);
|
|
3690
3742
|
session = {
|
|
3691
3743
|
version: 1,
|
|
3692
3744
|
config,
|
|
@@ -3732,7 +3784,7 @@ async function runSiblingCreateCommand(name, options) {
|
|
|
3732
3784
|
);
|
|
3733
3785
|
}
|
|
3734
3786
|
async function runSiblingCreate(github, aws, coreAws, git, config, session, options) {
|
|
3735
|
-
const totalSteps =
|
|
3787
|
+
const totalSteps = 8;
|
|
3736
3788
|
const { org, repo } = githubRepo(config);
|
|
3737
3789
|
const pathPrefix = resolvePathPrefix(config);
|
|
3738
3790
|
if (!session.completedSteps.includes("verify_credentials")) {
|
|
@@ -3768,54 +3820,67 @@ async function runSiblingCreate(github, aws, coreAws, git, config, session, opti
|
|
|
3768
3820
|
);
|
|
3769
3821
|
}
|
|
3770
3822
|
if (!session.completedSteps.includes("create_repo")) {
|
|
3771
|
-
log.step(3, totalSteps, "Creating GitHub repository
|
|
3772
|
-
|
|
3823
|
+
log.step(3, totalSteps, "Creating GitHub repository...");
|
|
3824
|
+
session.outputs.cloneUrl = await github.createEmptyRepo(
|
|
3773
3825
|
org,
|
|
3774
3826
|
repo,
|
|
3775
3827
|
config.project.description || void 0
|
|
3776
3828
|
);
|
|
3777
|
-
session.outputs.cloneUrl = cloneUrl;
|
|
3778
|
-
await pushSkeleton(
|
|
3779
|
-
git,
|
|
3780
|
-
options.skeletonRoot,
|
|
3781
|
-
cloneUrl,
|
|
3782
|
-
config,
|
|
3783
|
-
options.coreConfig,
|
|
3784
|
-
options.githubToken
|
|
3785
|
-
);
|
|
3786
3829
|
markSiblingStepComplete(session, "create_repo");
|
|
3787
3830
|
} else {
|
|
3788
3831
|
log.step(3, totalSteps, "GitHub repository already created \u2014 skipping");
|
|
3789
3832
|
}
|
|
3833
|
+
const cloneUrl = session.outputs.cloneUrl;
|
|
3834
|
+
if (!cloneUrl) {
|
|
3835
|
+
throw new Error("internal error: create_repo did not populate session.outputs.cloneUrl");
|
|
3836
|
+
}
|
|
3837
|
+
if (!session.completedSteps.includes("push_skeleton")) {
|
|
3838
|
+
if (await github.repoHasCommits(org, repo)) {
|
|
3839
|
+
log.step(4, totalSteps, "Sibling skeleton already pushed \u2014 skipping");
|
|
3840
|
+
} else {
|
|
3841
|
+
log.step(4, totalSteps, "Pushing sibling skeleton...");
|
|
3842
|
+
await pushSkeleton(
|
|
3843
|
+
git,
|
|
3844
|
+
options.skeletonRoot,
|
|
3845
|
+
cloneUrl,
|
|
3846
|
+
config,
|
|
3847
|
+
options.coreConfig,
|
|
3848
|
+
options.githubToken
|
|
3849
|
+
);
|
|
3850
|
+
}
|
|
3851
|
+
markSiblingStepComplete(session, "push_skeleton");
|
|
3852
|
+
} else {
|
|
3853
|
+
log.step(4, totalSteps, "Sibling skeleton already pushed \u2014 skipping");
|
|
3854
|
+
}
|
|
3790
3855
|
if (!session.completedSteps.includes("oidc_trust")) {
|
|
3791
|
-
log.step(
|
|
3856
|
+
log.step(5, totalSteps, "Configuring OIDC trust...");
|
|
3792
3857
|
session.outputs.oidcRoleArn = await aws.setupOidcTrust(
|
|
3793
3858
|
config,
|
|
3794
3859
|
await resolveRepoIds(github, config)
|
|
3795
3860
|
);
|
|
3796
3861
|
markSiblingStepComplete(session, "oidc_trust");
|
|
3797
3862
|
} else {
|
|
3798
|
-
log.step(
|
|
3863
|
+
log.step(5, totalSteps, "OIDC trust already configured \u2014 skipping");
|
|
3799
3864
|
}
|
|
3800
3865
|
if (!session.completedSteps.includes("terraform_backend")) {
|
|
3801
|
-
log.step(
|
|
3866
|
+
log.step(6, totalSteps, "Bootstrapping Terraform state backend...");
|
|
3802
3867
|
session.outputs.tfStateBucket = await aws.bootstrapTerraformBackend(config.project.name);
|
|
3803
3868
|
markSiblingStepComplete(session, "terraform_backend");
|
|
3804
3869
|
} else {
|
|
3805
|
-
log.step(
|
|
3870
|
+
log.step(6, totalSteps, "Terraform backend already bootstrapped \u2014 skipping");
|
|
3806
3871
|
}
|
|
3807
3872
|
if (!session.completedSteps.includes("github_config")) {
|
|
3808
|
-
log.step(
|
|
3873
|
+
log.step(7, totalSteps, "Configuring GitHub repository...");
|
|
3809
3874
|
await configureSiblingGithub(github, config, options.coreConfig, session, coreIdentity);
|
|
3810
3875
|
markSiblingStepComplete(session, "github_config");
|
|
3811
3876
|
} else {
|
|
3812
|
-
log.step(
|
|
3877
|
+
log.step(7, totalSteps, "GitHub already configured \u2014 skipping");
|
|
3813
3878
|
}
|
|
3814
3879
|
if (options.skipRegistration && !session.completedSteps.includes("register_with_core")) {
|
|
3815
|
-
log.step(
|
|
3880
|
+
log.step(8, totalSteps, "Already registered with the core project by `biffo init` \u2014 skipping");
|
|
3816
3881
|
markSiblingStepComplete(session, "register_with_core");
|
|
3817
3882
|
} else if (!session.completedSteps.includes("register_with_core")) {
|
|
3818
|
-
log.step(
|
|
3883
|
+
log.step(8, totalSteps, "Opening a registration PR against the core project...");
|
|
3819
3884
|
session.outputs.registrationPrUrl = await registerWithCore(
|
|
3820
3885
|
git,
|
|
3821
3886
|
github,
|
|
@@ -3826,7 +3891,7 @@ async function runSiblingCreate(github, aws, coreAws, git, config, session, opti
|
|
|
3826
3891
|
);
|
|
3827
3892
|
markSiblingStepComplete(session, "register_with_core");
|
|
3828
3893
|
} else {
|
|
3829
|
-
log.step(
|
|
3894
|
+
log.step(8, totalSteps, "Already registered with the core project \u2014 skipping");
|
|
3830
3895
|
}
|
|
3831
3896
|
deleteSiblingSession(config.project.name);
|
|
3832
3897
|
}
|
|
@@ -3972,7 +4037,10 @@ async function configureSiblingGithub(github, config, coreConfig, session, coreI
|
|
|
3972
4037
|
await github.createEnvironments(config);
|
|
3973
4038
|
await github.enableVulnerabilityAlerts(org, repo);
|
|
3974
4039
|
await github.setRepoVariable(org, repo, "PROJECT_NAME", config.project.name);
|
|
3975
|
-
|
|
4040
|
+
const pathPrefix = resolvePathPrefix(config);
|
|
4041
|
+
if (pathPrefix !== "") {
|
|
4042
|
+
await github.setRepoVariable(org, repo, "PATH_PREFIX", pathPrefix);
|
|
4043
|
+
}
|
|
3976
4044
|
await github.setRepoVariable(org, repo, "AWS_REGION", awsConfig(config).region);
|
|
3977
4045
|
await github.setRepoVariable(org, repo, "SIBLING_DEPLOY_ENABLED", "true");
|
|
3978
4046
|
try {
|
|
@@ -4178,14 +4246,7 @@ var initCommand = new Command12("init").description("Scaffold a new project from
|
|
|
4178
4246
|
const rawConfig = JSON.parse(readFileSync12(resolve10(options.config), "utf8"));
|
|
4179
4247
|
config = parseConfig(rawConfig);
|
|
4180
4248
|
const { account_id: accountId, region } = config.cloud.config;
|
|
4181
|
-
session =
|
|
4182
|
-
version: 1,
|
|
4183
|
-
config,
|
|
4184
|
-
awsAccountId: accountId,
|
|
4185
|
-
awsRegion: region,
|
|
4186
|
-
completedSteps: [],
|
|
4187
|
-
outputs: {}
|
|
4188
|
-
};
|
|
4249
|
+
session = resolveConfigFileSession(config, accountId, region, options.fresh === true);
|
|
4189
4250
|
} else {
|
|
4190
4251
|
githubToken = await resolveGithubToken3(options.yes === true);
|
|
4191
4252
|
const { accountId, region, profile } = await resolveAwsCredentials(options.yes === true);
|
|
@@ -4224,6 +4285,7 @@ var initCommand = new Command12("init").description("Scaffold a new project from
|
|
|
4224
4285
|
if (!session) {
|
|
4225
4286
|
const rawConfig = await promptForConfig(accountId, region, profile);
|
|
4226
4287
|
config = parseConfig(rawConfig);
|
|
4288
|
+
deleteSession(config.project.name);
|
|
4227
4289
|
session = {
|
|
4228
4290
|
version: 1,
|
|
4229
4291
|
config,
|
|
@@ -4267,6 +4329,22 @@ var initCommand = new Command12("init").description("Scaffold a new project from
|
|
|
4267
4329
|
);
|
|
4268
4330
|
}
|
|
4269
4331
|
);
|
|
4332
|
+
function resolveConfigFileSession(config, awsAccountId, awsRegion, fresh) {
|
|
4333
|
+
const saved = fresh ? null : loadSession(config.project.name);
|
|
4334
|
+
const session = saved ? { ...saved, config, awsAccountId, awsRegion } : { version: 1, config, awsAccountId, awsRegion, completedSteps: [], outputs: {} };
|
|
4335
|
+
if (saved) {
|
|
4336
|
+
console.log(
|
|
4337
|
+
chalk12.dim(
|
|
4338
|
+
` Resuming previous init for ${config.project.name} (completed: ${saved.completedSteps.join(", ") || "none"})
|
|
4339
|
+
`
|
|
4340
|
+
)
|
|
4341
|
+
);
|
|
4342
|
+
} else {
|
|
4343
|
+
deleteSession(config.project.name);
|
|
4344
|
+
}
|
|
4345
|
+
saveSession(session);
|
|
4346
|
+
return session;
|
|
4347
|
+
}
|
|
4270
4348
|
async function runInit(github, aws, config, session, appSibling) {
|
|
4271
4349
|
const totalSteps = appSibling ? 6 : 5;
|
|
4272
4350
|
if (!session.completedSteps.includes("verify_credentials")) {
|
|
@@ -4320,14 +4398,26 @@ async function runInit(github, aws, config, session, appSibling) {
|
|
|
4320
4398
|
};
|
|
4321
4399
|
}
|
|
4322
4400
|
}
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
const dns = resolveDnsConfig(config);
|
|
4327
|
-
const domain = dns.domain;
|
|
4401
|
+
const { org, repo } = config.source_control.config;
|
|
4402
|
+
if (!hasCompleted(session, "github_branches")) {
|
|
4403
|
+
log.step(5, totalSteps, "Creating dev and staging branches...");
|
|
4328
4404
|
await github.createBranch(org, repo, "dev", "main");
|
|
4329
4405
|
await github.createBranch(org, repo, "staging", "main");
|
|
4406
|
+
markStepComplete(session, "github_branches");
|
|
4407
|
+
} else {
|
|
4408
|
+
log.step(5, totalSteps, "Branches already created \u2014 skipping");
|
|
4409
|
+
}
|
|
4410
|
+
if (!hasCompleted(session, "github_instance_files")) {
|
|
4411
|
+
log.step(5, totalSteps, "Writing instance identity files...");
|
|
4330
4412
|
await writeInstanceFiles(github, org, repo, config);
|
|
4413
|
+
markStepComplete(session, "github_instance_files");
|
|
4414
|
+
} else {
|
|
4415
|
+
log.step(5, totalSteps, "Instance identity files already written \u2014 skipping");
|
|
4416
|
+
}
|
|
4417
|
+
if (!hasCompleted(session, "github_settings")) {
|
|
4418
|
+
log.step(5, totalSteps, "Configuring GitHub repository...");
|
|
4419
|
+
const dns = resolveDnsConfig(config);
|
|
4420
|
+
const domain = dns.domain;
|
|
4331
4421
|
await github.setDefaultBranch(org, repo, "dev");
|
|
4332
4422
|
await github.configureBranchProtection(config);
|
|
4333
4423
|
await github.createEnvironments(config);
|
|
@@ -4352,7 +4442,7 @@ async function runInit(github, aws, config, session, appSibling) {
|
|
|
4352
4442
|
if (session.outputs.oidcRoleArn) {
|
|
4353
4443
|
await github.setRepoSecret(org, repo, "BIFFO_OIDC_ROLE_ARN", session.outputs.oidcRoleArn);
|
|
4354
4444
|
}
|
|
4355
|
-
markStepComplete(session, "
|
|
4445
|
+
markStepComplete(session, "github_settings");
|
|
4356
4446
|
} else {
|
|
4357
4447
|
log.step(5, totalSteps, "GitHub already configured \u2014 skipping");
|
|
4358
4448
|
}
|
|
@@ -4371,6 +4461,9 @@ async function runInit(github, aws, config, session, appSibling) {
|
|
|
4371
4461
|
async function createAppSibling(github, config, session, deps) {
|
|
4372
4462
|
const siblingConfig = appSiblingConfig(config);
|
|
4373
4463
|
const cloud = config.cloud;
|
|
4464
|
+
if (!session.outputs.appSibling) {
|
|
4465
|
+
deleteSiblingSession(siblingConfig.project.name);
|
|
4466
|
+
}
|
|
4374
4467
|
session.outputs.appSibling ??= {
|
|
4375
4468
|
version: 1,
|
|
4376
4469
|
config: siblingConfig,
|