@factiii/stack 0.1.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/README.md +420 -0
- package/bin/factiii +229 -0
- package/dist/cli/check-config.d.ts +9 -0
- package/dist/cli/check-config.d.ts.map +1 -0
- package/dist/cli/check-config.js +19 -0
- package/dist/cli/check-config.js.map +1 -0
- package/dist/cli/deploy-secrets.d.ts +16 -0
- package/dist/cli/deploy-secrets.d.ts.map +1 -0
- package/dist/cli/deploy-secrets.js +227 -0
- package/dist/cli/deploy-secrets.js.map +1 -0
- package/dist/cli/deploy.d.ts +30 -0
- package/dist/cli/deploy.d.ts.map +1 -0
- package/dist/cli/deploy.js +306 -0
- package/dist/cli/deploy.js.map +1 -0
- package/dist/cli/deployer.d.ts +13 -0
- package/dist/cli/deployer.d.ts.map +1 -0
- package/dist/cli/deployer.js +21 -0
- package/dist/cli/deployer.js.map +1 -0
- package/dist/cli/dev-sync.d.ts +30 -0
- package/dist/cli/dev-sync.d.ts.map +1 -0
- package/dist/cli/dev-sync.js +500 -0
- package/dist/cli/dev-sync.js.map +1 -0
- package/dist/cli/execute-plugin-command.d.ts +25 -0
- package/dist/cli/execute-plugin-command.d.ts.map +1 -0
- package/dist/cli/execute-plugin-command.js +237 -0
- package/dist/cli/execute-plugin-command.js.map +1 -0
- package/dist/cli/fix.d.ts +22 -0
- package/dist/cli/fix.d.ts.map +1 -0
- package/dist/cli/fix.js +267 -0
- package/dist/cli/fix.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +31 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +9 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +190 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/plugin-commands.d.ts +22 -0
- package/dist/cli/plugin-commands.d.ts.map +1 -0
- package/dist/cli/plugin-commands.js +121 -0
- package/dist/cli/plugin-commands.js.map +1 -0
- package/dist/cli/scan.d.ts +66 -0
- package/dist/cli/scan.d.ts.map +1 -0
- package/dist/cli/scan.js +511 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/secrets.d.ts +19 -0
- package/dist/cli/secrets.d.ts.map +1 -0
- package/dist/cli/secrets.js +318 -0
- package/dist/cli/secrets.js.map +1 -0
- package/dist/cli/undeploy.d.ts +9 -0
- package/dist/cli/undeploy.d.ts.map +1 -0
- package/dist/cli/undeploy.js +95 -0
- package/dist/cli/undeploy.js.map +1 -0
- package/dist/cli/upgrade.d.ts +9 -0
- package/dist/cli/upgrade.d.ts.map +1 -0
- package/dist/cli/upgrade.js +24 -0
- package/dist/cli/upgrade.js.map +1 -0
- package/dist/cli/validate.d.ts +9 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +20 -0
- package/dist/cli/validate.js.map +1 -0
- package/dist/generators/generate-factiii-auto.d.ts +31 -0
- package/dist/generators/generate-factiii-auto.d.ts.map +1 -0
- package/dist/generators/generate-factiii-auto.js +251 -0
- package/dist/generators/generate-factiii-auto.js.map +1 -0
- package/dist/generators/generate-factiii-yml.d.ts +23 -0
- package/dist/generators/generate-factiii-yml.d.ts.map +1 -0
- package/dist/generators/generate-factiii-yml.js +228 -0
- package/dist/generators/generate-factiii-yml.js.map +1 -0
- package/dist/generators/index.d.ts +8 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +14 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/addons/server-mode/index.d.ts +57 -0
- package/dist/plugins/addons/server-mode/index.d.ts.map +1 -0
- package/dist/plugins/addons/server-mode/index.js +136 -0
- package/dist/plugins/addons/server-mode/index.js.map +1 -0
- package/dist/plugins/addons/server-mode/scanfix/mac.d.ts +17 -0
- package/dist/plugins/addons/server-mode/scanfix/mac.d.ts.map +1 -0
- package/dist/plugins/addons/server-mode/scanfix/mac.js +461 -0
- package/dist/plugins/addons/server-mode/scanfix/mac.js.map +1 -0
- package/dist/plugins/addons/server-mode/scanfix/ubuntu.d.ts +12 -0
- package/dist/plugins/addons/server-mode/scanfix/ubuntu.d.ts.map +1 -0
- package/dist/plugins/addons/server-mode/scanfix/ubuntu.js +246 -0
- package/dist/plugins/addons/server-mode/scanfix/ubuntu.js.map +1 -0
- package/dist/plugins/addons/server-mode/scanfix/windows.d.ts +14 -0
- package/dist/plugins/addons/server-mode/scanfix/windows.d.ts.map +1 -0
- package/dist/plugins/addons/server-mode/scanfix/windows.js +113 -0
- package/dist/plugins/addons/server-mode/scanfix/windows.js.map +1 -0
- package/dist/plugins/approved.json +13 -0
- package/dist/plugins/frameworks/prisma-trpc/index.d.ts +65 -0
- package/dist/plugins/frameworks/prisma-trpc/index.d.ts.map +1 -0
- package/dist/plugins/frameworks/prisma-trpc/index.js +668 -0
- package/dist/plugins/frameworks/prisma-trpc/index.js.map +1 -0
- package/dist/plugins/index.d.ts +101 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +411 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/interfaces/addon.d.ts +43 -0
- package/dist/plugins/interfaces/addon.d.ts.map +1 -0
- package/dist/plugins/interfaces/addon.js +53 -0
- package/dist/plugins/interfaces/addon.js.map +1 -0
- package/dist/plugins/interfaces/framework.d.ts +43 -0
- package/dist/plugins/interfaces/framework.d.ts.map +1 -0
- package/dist/plugins/interfaces/framework.js +53 -0
- package/dist/plugins/interfaces/framework.js.map +1 -0
- package/dist/plugins/interfaces/index.d.ts +10 -0
- package/dist/plugins/interfaces/index.d.ts.map +1 -0
- package/dist/plugins/interfaces/index.js +17 -0
- package/dist/plugins/interfaces/index.js.map +1 -0
- package/dist/plugins/interfaces/pipeline.d.ts +78 -0
- package/dist/plugins/interfaces/pipeline.d.ts.map +1 -0
- package/dist/plugins/interfaces/pipeline.js +82 -0
- package/dist/plugins/interfaces/pipeline.js.map +1 -0
- package/dist/plugins/interfaces/server.d.ts +65 -0
- package/dist/plugins/interfaces/server.d.ts.map +1 -0
- package/dist/plugins/interfaces/server.js +72 -0
- package/dist/plugins/interfaces/server.js.map +1 -0
- package/dist/plugins/pipelines/aws/configs/ec2.d.ts +9 -0
- package/dist/plugins/pipelines/aws/configs/ec2.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/configs/ec2.js +34 -0
- package/dist/plugins/pipelines/aws/configs/ec2.js.map +1 -0
- package/dist/plugins/pipelines/aws/configs/free-tier.d.ts +13 -0
- package/dist/plugins/pipelines/aws/configs/free-tier.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/configs/free-tier.js +86 -0
- package/dist/plugins/pipelines/aws/configs/free-tier.js.map +1 -0
- package/dist/plugins/pipelines/aws/configs/index.d.ts +14 -0
- package/dist/plugins/pipelines/aws/configs/index.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/configs/index.js +21 -0
- package/dist/plugins/pipelines/aws/configs/index.js.map +1 -0
- package/dist/plugins/pipelines/aws/configs/types.d.ts +36 -0
- package/dist/plugins/pipelines/aws/configs/types.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/configs/types.js +9 -0
- package/dist/plugins/pipelines/aws/configs/types.js.map +1 -0
- package/dist/plugins/pipelines/aws/dev.d.ts +10 -0
- package/dist/plugins/pipelines/aws/dev.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/dev.js +70 -0
- package/dist/plugins/pipelines/aws/dev.js.map +1 -0
- package/dist/plugins/pipelines/aws/index.d.ts +118 -0
- package/dist/plugins/pipelines/aws/index.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/index.js +346 -0
- package/dist/plugins/pipelines/aws/index.js.map +1 -0
- package/dist/plugins/pipelines/aws/prod.d.ts +19 -0
- package/dist/plugins/pipelines/aws/prod.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/prod.js +362 -0
- package/dist/plugins/pipelines/aws/prod.js.map +1 -0
- package/dist/plugins/pipelines/aws/scanfix/aws-cli.d.ts +7 -0
- package/dist/plugins/pipelines/aws/scanfix/aws-cli.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/scanfix/aws-cli.js +31 -0
- package/dist/plugins/pipelines/aws/scanfix/aws-cli.js.map +1 -0
- package/dist/plugins/pipelines/aws/scanfix/config.d.ts +7 -0
- package/dist/plugins/pipelines/aws/scanfix/config.d.ts.map +1 -0
- package/dist/plugins/pipelines/aws/scanfix/config.js +134 -0
- package/dist/plugins/pipelines/aws/scanfix/config.js.map +1 -0
- package/dist/plugins/pipelines/factiii/github-secrets-store.d.ts +65 -0
- package/dist/plugins/pipelines/factiii/github-secrets-store.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/github-secrets-store.js +221 -0
- package/dist/plugins/pipelines/factiii/github-secrets-store.js.map +1 -0
- package/dist/plugins/pipelines/factiii/index.d.ts +195 -0
- package/dist/plugins/pipelines/factiii/index.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/index.js +862 -0
- package/dist/plugins/pipelines/factiii/index.js.map +1 -0
- package/dist/plugins/pipelines/factiii/prod.d.ts +17 -0
- package/dist/plugins/pipelines/factiii/prod.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/prod.js +282 -0
- package/dist/plugins/pipelines/factiii/prod.js.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/config.d.ts +7 -0
- package/dist/plugins/pipelines/factiii/scanfix/config.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/config.js +80 -0
- package/dist/plugins/pipelines/factiii/scanfix/config.js.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/github-cli.d.ts +7 -0
- package/dist/plugins/pipelines/factiii/scanfix/github-cli.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/github-cli.js +43 -0
- package/dist/plugins/pipelines/factiii/scanfix/github-cli.js.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/secrets.d.ts +7 -0
- package/dist/plugins/pipelines/factiii/scanfix/secrets.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/secrets.js +237 -0
- package/dist/plugins/pipelines/factiii/scanfix/secrets.js.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/workflows.d.ts +7 -0
- package/dist/plugins/pipelines/factiii/scanfix/workflows.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/scanfix/workflows.js +169 -0
- package/dist/plugins/pipelines/factiii/scanfix/workflows.js.map +1 -0
- package/dist/plugins/pipelines/factiii/staging.d.ts +25 -0
- package/dist/plugins/pipelines/factiii/staging.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/staging.js +223 -0
- package/dist/plugins/pipelines/factiii/staging.js.map +1 -0
- package/dist/plugins/pipelines/factiii/utils/detection.d.ts +36 -0
- package/dist/plugins/pipelines/factiii/utils/detection.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/utils/detection.js +140 -0
- package/dist/plugins/pipelines/factiii/utils/detection.js.map +1 -0
- package/dist/plugins/pipelines/factiii/utils/workflows.d.ts +16 -0
- package/dist/plugins/pipelines/factiii/utils/workflows.d.ts.map +1 -0
- package/dist/plugins/pipelines/factiii/utils/workflows.js +129 -0
- package/dist/plugins/pipelines/factiii/utils/workflows.js.map +1 -0
- package/dist/plugins/pipelines/factiii/workflows/factiii-cicd-prod.yml +112 -0
- package/dist/plugins/pipelines/factiii/workflows/factiii-cicd-staging.yml +112 -0
- package/dist/plugins/pipelines/factiii/workflows/factiii-command.yml +130 -0
- package/dist/plugins/pipelines/factiii/workflows/factiii-deploy.yml +198 -0
- package/dist/plugins/pipelines/factiii/workflows/factiii-dev-sync.yml +179 -0
- package/dist/plugins/pipelines/factiii/workflows/factiii-fix.yml +176 -0
- package/dist/plugins/pipelines/factiii/workflows/factiii-scan.yml +176 -0
- package/dist/plugins/pipelines/factiii/workflows/factiii-undeploy.yml +95 -0
- package/dist/plugins/servers/amazon-linux/index.d.ts +93 -0
- package/dist/plugins/servers/amazon-linux/index.d.ts.map +1 -0
- package/dist/plugins/servers/amazon-linux/index.js +217 -0
- package/dist/plugins/servers/amazon-linux/index.js.map +1 -0
- package/dist/plugins/servers/mac/dev.d.ts +10 -0
- package/dist/plugins/servers/mac/dev.d.ts.map +1 -0
- package/dist/plugins/servers/mac/dev.js +71 -0
- package/dist/plugins/servers/mac/dev.js.map +1 -0
- package/dist/plugins/servers/mac/index.d.ts +101 -0
- package/dist/plugins/servers/mac/index.d.ts.map +1 -0
- package/dist/plugins/servers/mac/index.js +257 -0
- package/dist/plugins/servers/mac/index.js.map +1 -0
- package/dist/plugins/servers/mac/scanfix/config.d.ts +7 -0
- package/dist/plugins/servers/mac/scanfix/config.d.ts.map +1 -0
- package/dist/plugins/servers/mac/scanfix/config.js +168 -0
- package/dist/plugins/servers/mac/scanfix/config.js.map +1 -0
- package/dist/plugins/servers/mac/scanfix/containers.d.ts +7 -0
- package/dist/plugins/servers/mac/scanfix/containers.d.ts.map +1 -0
- package/dist/plugins/servers/mac/scanfix/containers.js +167 -0
- package/dist/plugins/servers/mac/scanfix/containers.js.map +1 -0
- package/dist/plugins/servers/mac/scanfix/system.d.ts +7 -0
- package/dist/plugins/servers/mac/scanfix/system.d.ts.map +1 -0
- package/dist/plugins/servers/mac/scanfix/system.js +144 -0
- package/dist/plugins/servers/mac/scanfix/system.js.map +1 -0
- package/dist/plugins/servers/mac/staging.d.ts +21 -0
- package/dist/plugins/servers/mac/staging.d.ts.map +1 -0
- package/dist/plugins/servers/mac/staging.js +708 -0
- package/dist/plugins/servers/mac/staging.js.map +1 -0
- package/dist/plugins/servers/ubuntu/index.d.ts +93 -0
- package/dist/plugins/servers/ubuntu/index.d.ts.map +1 -0
- package/dist/plugins/servers/ubuntu/index.js +224 -0
- package/dist/plugins/servers/ubuntu/index.js.map +1 -0
- package/dist/plugins/servers/windows/index.d.ts +90 -0
- package/dist/plugins/servers/windows/index.d.ts.map +1 -0
- package/dist/plugins/servers/windows/index.js +205 -0
- package/dist/plugins/servers/windows/index.js.map +1 -0
- package/dist/scanfix/commands/index.d.ts +27 -0
- package/dist/scanfix/commands/index.d.ts.map +1 -0
- package/dist/scanfix/commands/index.js +97 -0
- package/dist/scanfix/commands/index.js.map +1 -0
- package/dist/scanfix/commands/mac.d.ts +11 -0
- package/dist/scanfix/commands/mac.d.ts.map +1 -0
- package/dist/scanfix/commands/mac.js +31 -0
- package/dist/scanfix/commands/mac.js.map +1 -0
- package/dist/scanfix/commands/ubuntu.d.ts +11 -0
- package/dist/scanfix/commands/ubuntu.d.ts.map +1 -0
- package/dist/scanfix/commands/ubuntu.js +30 -0
- package/dist/scanfix/commands/ubuntu.js.map +1 -0
- package/dist/scanfix/fixes/certbot.d.ts +25 -0
- package/dist/scanfix/fixes/certbot.d.ts.map +1 -0
- package/dist/scanfix/fixes/certbot.js +136 -0
- package/dist/scanfix/fixes/certbot.js.map +1 -0
- package/dist/scanfix/fixes/docker.d.ts +29 -0
- package/dist/scanfix/fixes/docker.d.ts.map +1 -0
- package/dist/scanfix/fixes/docker.js +149 -0
- package/dist/scanfix/fixes/docker.js.map +1 -0
- package/dist/scanfix/fixes/git.d.ts +20 -0
- package/dist/scanfix/fixes/git.d.ts.map +1 -0
- package/dist/scanfix/fixes/git.js +71 -0
- package/dist/scanfix/fixes/git.js.map +1 -0
- package/dist/scanfix/fixes/index.d.ts +11 -0
- package/dist/scanfix/fixes/index.d.ts.map +1 -0
- package/dist/scanfix/fixes/index.js +27 -0
- package/dist/scanfix/fixes/index.js.map +1 -0
- package/dist/scanfix/fixes/node.d.ts +20 -0
- package/dist/scanfix/fixes/node.d.ts.map +1 -0
- package/dist/scanfix/fixes/node.js +71 -0
- package/dist/scanfix/fixes/node.js.map +1 -0
- package/dist/scanfix/fixes/pnpm.d.ts +20 -0
- package/dist/scanfix/fixes/pnpm.d.ts.map +1 -0
- package/dist/scanfix/fixes/pnpm.js +122 -0
- package/dist/scanfix/fixes/pnpm.js.map +1 -0
- package/dist/scanfix/index.d.ts +23 -0
- package/dist/scanfix/index.d.ts.map +1 -0
- package/dist/scanfix/index.js +44 -0
- package/dist/scanfix/index.js.map +1 -0
- package/dist/scanfix/platform.d.ts +20 -0
- package/dist/scanfix/platform.d.ts.map +1 -0
- package/dist/scanfix/platform.js +48 -0
- package/dist/scanfix/platform.js.map +1 -0
- package/dist/scanfix/ssl-cert-helper.d.ts +27 -0
- package/dist/scanfix/ssl-cert-helper.d.ts.map +1 -0
- package/dist/scanfix/ssl-cert-helper.js +117 -0
- package/dist/scanfix/ssl-cert-helper.js.map +1 -0
- package/dist/scanfix/types.d.ts +27 -0
- package/dist/scanfix/types.d.ts.map +1 -0
- package/dist/scanfix/types.js +8 -0
- package/dist/scanfix/types.js.map +1 -0
- package/dist/scripts/check-existing-secrets.d.ts +6 -0
- package/dist/scripts/check-existing-secrets.d.ts.map +1 -0
- package/dist/scripts/check-existing-secrets.js +86 -0
- package/dist/scripts/check-existing-secrets.js.map +1 -0
- package/dist/scripts/generate-all.d.ts +40 -0
- package/dist/scripts/generate-all.d.ts.map +1 -0
- package/dist/scripts/generate-all.js +373 -0
- package/dist/scripts/generate-all.js.map +1 -0
- package/dist/scripts/get-repo-name.d.ts +6 -0
- package/dist/scripts/get-repo-name.d.ts.map +1 -0
- package/dist/scripts/get-repo-name.js +54 -0
- package/dist/scripts/get-repo-name.js.map +1 -0
- package/dist/scripts/index.d.ts +7 -0
- package/dist/scripts/index.d.ts.map +1 -0
- package/dist/scripts/index.js +14 -0
- package/dist/scripts/index.js.map +1 -0
- package/dist/scripts/validate-env-files.d.ts +6 -0
- package/dist/scripts/validate-env-files.d.ts.map +1 -0
- package/dist/scripts/validate-env-files.js +126 -0
- package/dist/scripts/validate-env-files.js.map +1 -0
- package/dist/scripts/validate-example-values.d.ts +8 -0
- package/dist/scripts/validate-example-values.d.ts.map +1 -0
- package/dist/scripts/validate-example-values.js +88 -0
- package/dist/scripts/validate-example-values.js.map +1 -0
- package/dist/scripts/validate-factiii-yml.d.ts +6 -0
- package/dist/scripts/validate-factiii-yml.d.ts.map +1 -0
- package/dist/scripts/validate-factiii-yml.js +71 -0
- package/dist/scripts/validate-factiii-yml.js.map +1 -0
- package/dist/types/cli.d.ts +138 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/cli.js +8 -0
- package/dist/types/cli.js.map +1 -0
- package/dist/types/config.d.ts +113 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +8 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +25 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/plugin.d.ts +352 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/plugin.js +8 -0
- package/dist/types/plugin.js.map +1 -0
- package/dist/utils/ansible-vault-secrets.d.ts +95 -0
- package/dist/utils/ansible-vault-secrets.d.ts.map +1 -0
- package/dist/utils/ansible-vault-secrets.js +406 -0
- package/dist/utils/ansible-vault-secrets.js.map +1 -0
- package/dist/utils/config-helpers.d.ts +72 -0
- package/dist/utils/config-helpers.d.ts.map +1 -0
- package/dist/utils/config-helpers.js +171 -0
- package/dist/utils/config-helpers.js.map +1 -0
- package/dist/utils/config-schema.d.ts +17 -0
- package/dist/utils/config-schema.d.ts.map +1 -0
- package/dist/utils/config-schema.js +100 -0
- package/dist/utils/config-schema.js.map +1 -0
- package/dist/utils/config-validator.d.ts +29 -0
- package/dist/utils/config-validator.d.ts.map +1 -0
- package/dist/utils/config-validator.js +146 -0
- package/dist/utils/config-validator.js.map +1 -0
- package/dist/utils/deployment-report.d.ts +100 -0
- package/dist/utils/deployment-report.d.ts.map +1 -0
- package/dist/utils/deployment-report.js +225 -0
- package/dist/utils/deployment-report.js.map +1 -0
- package/dist/utils/dns-validator.d.ts +19 -0
- package/dist/utils/dns-validator.d.ts.map +1 -0
- package/dist/utils/dns-validator.js +94 -0
- package/dist/utils/dns-validator.js.map +1 -0
- package/dist/utils/env-validator.d.ts +108 -0
- package/dist/utils/env-validator.d.ts.map +1 -0
- package/dist/utils/env-validator.js +342 -0
- package/dist/utils/env-validator.js.map +1 -0
- package/dist/utils/github-workflow-monitor.d.ts +49 -0
- package/dist/utils/github-workflow-monitor.d.ts.map +1 -0
- package/dist/utils/github-workflow-monitor.js +145 -0
- package/dist/utils/github-workflow-monitor.js.map +1 -0
- package/dist/utils/index.d.ts +18 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +48 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/secret-prompts.d.ts +67 -0
- package/dist/utils/secret-prompts.d.ts.map +1 -0
- package/dist/utils/secret-prompts.js +369 -0
- package/dist/utils/secret-prompts.js.map +1 -0
- package/dist/utils/server-check.d.ts +43 -0
- package/dist/utils/server-check.d.ts.map +1 -0
- package/dist/utils/server-check.js +397 -0
- package/dist/utils/server-check.js.map +1 -0
- package/dist/utils/ssh-deploy.d.ts +70 -0
- package/dist/utils/ssh-deploy.d.ts.map +1 -0
- package/dist/utils/ssh-deploy.js +268 -0
- package/dist/utils/ssh-deploy.js.map +1 -0
- package/dist/utils/ssh-helper.d.ts +40 -0
- package/dist/utils/ssh-helper.d.ts.map +1 -0
- package/dist/utils/ssh-helper.js +221 -0
- package/dist/utils/ssh-helper.js.map +1 -0
- package/dist/utils/template-generator.d.ts +42 -0
- package/dist/utils/template-generator.d.ts.map +1 -0
- package/dist/utils/template-generator.js +223 -0
- package/dist/utils/template-generator.js.map +1 -0
- package/dist/utils/version-check.d.ts +69 -0
- package/dist/utils/version-check.d.ts.map +1 -0
- package/dist/utils/version-check.js +211 -0
- package/dist/utils/version-check.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Staging environment operations for macOS plugin
|
|
4
|
+
* Handles staging deployment, server preparation, and staging-specific helpers
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
40
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.ensureServerReady = ensureServerReady;
|
|
44
|
+
exports.deployStaging = deployStaging;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const child_process_1 = require("child_process");
|
|
48
|
+
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
49
|
+
const ssh_helper_js_1 = require("../../../utils/ssh-helper.js");
|
|
50
|
+
const config_helpers_js_1 = require("../../../utils/config-helpers.js");
|
|
51
|
+
const index_js_1 = require("../../../scripts/index.js");
|
|
52
|
+
/**
|
|
53
|
+
* Execute a command on a remote server via SSH
|
|
54
|
+
*/
|
|
55
|
+
async function sshExecCommand(envConfig, command) {
|
|
56
|
+
return await (0, ssh_helper_js_1.sshExec)(envConfig, command);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Ensure Node.js is installed on the server
|
|
60
|
+
*/
|
|
61
|
+
async function ensureNodeInstalled(envConfig) {
|
|
62
|
+
try {
|
|
63
|
+
await sshExecCommand(envConfig, 'which node');
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
console.log(' Installing Node.js...');
|
|
67
|
+
await sshExecCommand(envConfig, 'brew install node || (curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs)');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Ensure git is installed on the server
|
|
72
|
+
*/
|
|
73
|
+
async function ensureGitInstalled(envConfig) {
|
|
74
|
+
try {
|
|
75
|
+
await sshExecCommand(envConfig, 'which git');
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
console.log(' Installing git...');
|
|
79
|
+
await sshExecCommand(envConfig, 'brew install git || sudo apt-get install -y git');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Ensure pnpm is installed on the server
|
|
84
|
+
*/
|
|
85
|
+
async function ensurePnpmInstalled(envConfig) {
|
|
86
|
+
try {
|
|
87
|
+
await sshExecCommand(envConfig, 'which pnpm');
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
console.log(' Installing pnpm...');
|
|
91
|
+
await sshExecCommand(envConfig, 'npm install -g pnpm@9');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Ensure repository is cloned
|
|
96
|
+
*/
|
|
97
|
+
async function ensureRepoCloned(envConfig, repoUrl, repoDir, repoName) {
|
|
98
|
+
const checkExists = await sshExecCommand(envConfig, `test -d ${repoDir}/.git && echo "exists" || echo "missing"`);
|
|
99
|
+
if (checkExists.includes('missing')) {
|
|
100
|
+
console.log(' Cloning repository...');
|
|
101
|
+
// Extract GitHub repo from URL if provided, otherwise use GITHUB_REPO env var
|
|
102
|
+
let gitUrl = repoUrl;
|
|
103
|
+
if (repoUrl && !repoUrl.startsWith('git@') && !repoUrl.startsWith('https://')) {
|
|
104
|
+
// Format: owner/repo
|
|
105
|
+
gitUrl = `git@github.com:${repoUrl}.git`;
|
|
106
|
+
}
|
|
107
|
+
await sshExecCommand(envConfig, `mkdir -p ~/.factiii && cd ~/.factiii && git clone ${gitUrl} ${repoName}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Pull latest changes and checkout specific commit
|
|
112
|
+
*/
|
|
113
|
+
async function pullAndCheckout(envConfig, repoDir, branch, commitHash) {
|
|
114
|
+
console.log(` Checking out ${branch}${commitHash ? ' @ ' + commitHash.substring(0, 7) : ''}...`);
|
|
115
|
+
const commands = [
|
|
116
|
+
`cd ${repoDir}`,
|
|
117
|
+
'git fetch --all',
|
|
118
|
+
`git checkout ${branch}`,
|
|
119
|
+
`git pull origin ${branch}`,
|
|
120
|
+
];
|
|
121
|
+
// If commit hash provided, checkout that specific commit
|
|
122
|
+
if (commitHash) {
|
|
123
|
+
commands.push(`git checkout ${commitHash}`);
|
|
124
|
+
}
|
|
125
|
+
await sshExecCommand(envConfig, commands.join(' && '));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Install dependencies using pnpm
|
|
129
|
+
*/
|
|
130
|
+
async function installDependencies(envConfig, repoDir) {
|
|
131
|
+
await sshExecCommand(envConfig, `cd ${repoDir} && pnpm install`);
|
|
132
|
+
}
|
|
133
|
+
// ============================================================
|
|
134
|
+
// CRITICAL: SSL Certificate Management
|
|
135
|
+
// ============================================================
|
|
136
|
+
// Why this exists: Automatically obtain/renew Let's Encrypt SSL certificates
|
|
137
|
+
// What breaks if changed: HTTPS will fail, browsers show security warnings
|
|
138
|
+
// Dependencies: Docker must be installed, ssl_email must be configured
|
|
139
|
+
// Uses Docker certbot for portability (no host certbot installation needed)
|
|
140
|
+
// ============================================================
|
|
141
|
+
/**
|
|
142
|
+
* Run certbot to obtain/renew SSL certificates using Docker
|
|
143
|
+
* Called after nginx.conf is generated but before containers start
|
|
144
|
+
* Collects all domains from all environments in factiii.yml and obtains certificates
|
|
145
|
+
* Uses standalone mode with Docker certbot (nginx must be stopped first)
|
|
146
|
+
*/
|
|
147
|
+
async function runCertbot(envConfig, config) {
|
|
148
|
+
const environments = (0, config_helpers_js_1.extractEnvironments)(config);
|
|
149
|
+
// Collect all domains that need certificates
|
|
150
|
+
const domains = [];
|
|
151
|
+
for (const env of Object.values(environments)) {
|
|
152
|
+
if (env.domain && !env.domain.startsWith('EXAMPLE-')) {
|
|
153
|
+
domains.push(env.domain);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (domains.length === 0) {
|
|
157
|
+
console.log(' No domains configured, skipping SSL certificates');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const sslEmail = config.ssl_email;
|
|
161
|
+
if (!sslEmail || sslEmail.startsWith('EXAMPLE-')) {
|
|
162
|
+
console.log(' ⚠️ ssl_email not configured in factiii.yml, skipping SSL');
|
|
163
|
+
console.log(' Add ssl_email to factiii.yml to enable automatic SSL certificates');
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const isOnServer = process.env.GITHUB_ACTIONS === 'true';
|
|
167
|
+
// For each domain, obtain certificate using Docker certbot
|
|
168
|
+
for (const domain of domains) {
|
|
169
|
+
console.log(` Obtaining SSL certificate for: ${domain}`);
|
|
170
|
+
// Build Docker certbot command (standalone mode - port 80 must be free)
|
|
171
|
+
const certbotCmd = [
|
|
172
|
+
'docker run --rm',
|
|
173
|
+
'-v /etc/letsencrypt:/etc/letsencrypt',
|
|
174
|
+
'-v /var/lib/letsencrypt:/var/lib/letsencrypt',
|
|
175
|
+
'-p 80:80',
|
|
176
|
+
'certbot/certbot certonly',
|
|
177
|
+
'--standalone',
|
|
178
|
+
'-d ' + domain,
|
|
179
|
+
'--email ' + sslEmail,
|
|
180
|
+
'--agree-tos',
|
|
181
|
+
'--non-interactive',
|
|
182
|
+
].join(' ');
|
|
183
|
+
try {
|
|
184
|
+
if (isOnServer) {
|
|
185
|
+
// We're on the server - run directly
|
|
186
|
+
(0, child_process_1.execSync)(certbotCmd, {
|
|
187
|
+
stdio: 'inherit',
|
|
188
|
+
shell: '/bin/bash',
|
|
189
|
+
env: {
|
|
190
|
+
...process.env,
|
|
191
|
+
PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH}`,
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// We're remote - SSH to server
|
|
197
|
+
await sshExecCommand(envConfig, `export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" && ${certbotCmd}`);
|
|
198
|
+
}
|
|
199
|
+
console.log(` ✅ SSL certificate obtained for ${domain}`);
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
console.log(` ⚠️ Certbot failed for ${domain}, continuing without SSL`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Setup automatic certificate renewal via cron using Docker certbot
|
|
208
|
+
* Only runs once - checks if renewal is already configured
|
|
209
|
+
*/
|
|
210
|
+
async function setupCertbotRenewal(envConfig) {
|
|
211
|
+
console.log(' Setting up automatic certificate renewal...');
|
|
212
|
+
const isOnServer = process.env.GITHUB_ACTIONS === 'true';
|
|
213
|
+
// Docker certbot renewal command (webroot mode since nginx will be running)
|
|
214
|
+
const renewCmd = 'docker run --rm -v /etc/letsencrypt:/etc/letsencrypt -v /var/lib/letsencrypt:/var/lib/letsencrypt -v /var/www/certbot:/var/www/certbot certbot/certbot renew --quiet && docker exec factiii_nginx nginx -s reload';
|
|
215
|
+
if (isOnServer) {
|
|
216
|
+
// Check if certbot renewal is already configured
|
|
217
|
+
try {
|
|
218
|
+
const result = (0, child_process_1.execSync)('crontab -l 2>/dev/null | grep "certbot/certbot renew" || echo "NOT_FOUND"', {
|
|
219
|
+
encoding: 'utf-8',
|
|
220
|
+
shell: '/bin/bash',
|
|
221
|
+
});
|
|
222
|
+
if (result.includes('NOT_FOUND')) {
|
|
223
|
+
// Add renewal cron job (runs twice daily)
|
|
224
|
+
(0, child_process_1.execSync)(`(crontab -l 2>/dev/null; echo "0 0,12 * * * ${renewCmd}") | crontab -`, { stdio: 'inherit', shell: '/bin/bash' });
|
|
225
|
+
console.log(' ✅ Configured automatic certificate renewal (twice daily)');
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
console.log(' ✅ Certificate renewal already configured');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
console.log(' ⚠️ Could not configure certificate renewal');
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
// Check if certbot renewal is already configured
|
|
237
|
+
const cronCheck = await sshExecCommand(envConfig, 'crontab -l 2>/dev/null | grep "certbot/certbot renew" || echo "NOT_FOUND"');
|
|
238
|
+
if (cronCheck.includes('NOT_FOUND')) {
|
|
239
|
+
// Add renewal cron job (runs twice daily)
|
|
240
|
+
await sshExecCommand(envConfig, `(crontab -l 2>/dev/null; echo "0 0,12 * * * ${renewCmd}") | crontab -`);
|
|
241
|
+
console.log(' ✅ Configured automatic certificate renewal (twice daily)');
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
console.log(' ✅ Certificate renewal already configured');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Write environment variables to .env file on server
|
|
250
|
+
* Handles both local (on-server) and remote (SSH) execution
|
|
251
|
+
*/
|
|
252
|
+
async function writeEnvFile(envConfig, repoDir, environment, envVarsString) {
|
|
253
|
+
if (!envVarsString) {
|
|
254
|
+
// If no env vars provided, skip writing (allow manual .env files)
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const envFileName = `.env.${environment === 'production' ? 'prod' : environment}`;
|
|
258
|
+
const isOnServer = process.env.GITHUB_ACTIONS === 'true';
|
|
259
|
+
// Parse env vars string (newline-separated KEY=VALUE format)
|
|
260
|
+
const envVars = envVarsString
|
|
261
|
+
.split('\n')
|
|
262
|
+
.map((line) => line.trim())
|
|
263
|
+
.filter((line) => line && !line.startsWith('#'))
|
|
264
|
+
.filter((line) => line.includes('='));
|
|
265
|
+
if (envVars.length === 0) {
|
|
266
|
+
console.log(` ⚠️ No environment variables found in ${environment} secrets`);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
// Build env file content
|
|
270
|
+
const envFileContent = envVars.join('\n') + '\n';
|
|
271
|
+
if (isOnServer) {
|
|
272
|
+
// We're on the server - write directly
|
|
273
|
+
const expandedRepoDir = repoDir.replace('~', process.env.HOME ?? '/Users/jon');
|
|
274
|
+
const envFilePath = path.join(expandedRepoDir, envFileName);
|
|
275
|
+
console.log(` 📝 Writing ${envFileName} (${envVars.length} variables)...`);
|
|
276
|
+
fs.writeFileSync(envFilePath, envFileContent, 'utf8');
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
// We're remote - SSH to write
|
|
280
|
+
console.log(` 📝 Writing ${envFileName} on remote server (${envVars.length} variables)...`);
|
|
281
|
+
// Escape the content for shell
|
|
282
|
+
const escapedContent = envFileContent
|
|
283
|
+
.replace(/'/g, "'\\''")
|
|
284
|
+
.replace(/\n/g, '\\n');
|
|
285
|
+
await sshExecCommand(envConfig, `cat > ${repoDir}/${envFileName} << 'ENVEOF'
|
|
286
|
+
${envFileContent}ENVEOF`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Create .env file from .env.staging for host commands
|
|
291
|
+
* Replaces postgres:5432 with localhost:5438 so host commands can connect
|
|
292
|
+
* Handles both local (on-server) and remote (SSH) execution
|
|
293
|
+
*/
|
|
294
|
+
async function createEnvFromStaging(envConfig, repoDir) {
|
|
295
|
+
const isOnServer = process.env.GITHUB_ACTIONS === 'true';
|
|
296
|
+
const stagingEnvPath = isOnServer
|
|
297
|
+
? path.join(repoDir.replace('~', process.env.HOME ?? '/Users/jon'), '.env.staging')
|
|
298
|
+
: `${repoDir}/.env.staging`;
|
|
299
|
+
const envPath = isOnServer
|
|
300
|
+
? path.join(repoDir.replace('~', process.env.HOME ?? '/Users/jon'), '.env')
|
|
301
|
+
: `${repoDir}/.env`;
|
|
302
|
+
// Read .env.staging
|
|
303
|
+
let envContent;
|
|
304
|
+
if (isOnServer) {
|
|
305
|
+
if (!fs.existsSync(stagingEnvPath)) {
|
|
306
|
+
// .env.staging might not exist yet, skip gracefully
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
envContent = fs.readFileSync(stagingEnvPath, 'utf8');
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
// Remote - read via SSH
|
|
313
|
+
try {
|
|
314
|
+
envContent = await sshExecCommand(envConfig, `cat ${stagingEnvPath}`);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
// .env.staging might not exist yet, skip gracefully
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Replace postgres:5432 with localhost:5438 in DATABASE_URL and TEST_DATABASE_URL
|
|
322
|
+
// This allows host commands to connect via the exposed port
|
|
323
|
+
const updatedContent = envContent
|
|
324
|
+
.split('\n')
|
|
325
|
+
.map((line) => {
|
|
326
|
+
// Match DATABASE_URL or TEST_DATABASE_URL lines
|
|
327
|
+
if (line.match(/^(DATABASE_URL|TEST_DATABASE_URL)=/)) {
|
|
328
|
+
// Replace postgres:5432 with localhost:5438
|
|
329
|
+
// Handle both postgresql:// and postgres:// protocols
|
|
330
|
+
return line.replace(/@postgres:5432\//g, '@localhost:5438/');
|
|
331
|
+
}
|
|
332
|
+
return line;
|
|
333
|
+
})
|
|
334
|
+
.join('\n');
|
|
335
|
+
// Write to .env file
|
|
336
|
+
if (isOnServer) {
|
|
337
|
+
fs.writeFileSync(envPath, updatedContent, 'utf8');
|
|
338
|
+
console.log(' 📝 Created .env from .env.staging (with host port replacement)');
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
await sshExecCommand(envConfig, `cat > ${envPath} << 'ENVEOF'
|
|
342
|
+
${updatedContent}ENVEOF`);
|
|
343
|
+
console.log(' 📝 Created .env from .env.staging on remote server (with host port replacement)');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Ensure server is ready for deployment
|
|
348
|
+
* Installs Node.js, git, pnpm, clones repo, checks out commit
|
|
349
|
+
*/
|
|
350
|
+
async function ensureServerReady(config, environment, options = {}) {
|
|
351
|
+
// macOS server only handles staging-type environments (staging, staging2, etc.)
|
|
352
|
+
if (!environment.startsWith('staging') && !environment.startsWith('stage-')) {
|
|
353
|
+
return { success: true, message: 'macOS server only handles staging environments' };
|
|
354
|
+
}
|
|
355
|
+
// Get environment config (supports both v1.x and v2.0.0+ formats)
|
|
356
|
+
const environments = (0, config_helpers_js_1.extractEnvironments)(config);
|
|
357
|
+
const envConfig = environments[environment];
|
|
358
|
+
if (!envConfig?.domain) {
|
|
359
|
+
throw new Error(`${environment} domain not configured`);
|
|
360
|
+
}
|
|
361
|
+
const { commitHash, branch = 'main', repoUrl } = options;
|
|
362
|
+
const repoName = config.name ?? 'app';
|
|
363
|
+
const repoDir = `~/.factiii/${repoName}`;
|
|
364
|
+
try {
|
|
365
|
+
// 1. Ensure Node.js is installed
|
|
366
|
+
console.log(' Checking Node.js...');
|
|
367
|
+
await ensureNodeInstalled(envConfig);
|
|
368
|
+
// 2. Ensure git is installed
|
|
369
|
+
console.log(' Checking git...');
|
|
370
|
+
await ensureGitInstalled(envConfig);
|
|
371
|
+
// 3. Ensure repo is cloned and up to date
|
|
372
|
+
console.log(' Syncing repository...');
|
|
373
|
+
await ensureRepoCloned(envConfig, repoUrl, repoDir, repoName);
|
|
374
|
+
await pullAndCheckout(envConfig, repoDir, branch, commitHash);
|
|
375
|
+
// 4. Ensure pnpm is installed
|
|
376
|
+
console.log(' Checking pnpm...');
|
|
377
|
+
await ensurePnpmInstalled(envConfig);
|
|
378
|
+
// 5. Install dependencies
|
|
379
|
+
console.log(' Installing dependencies...');
|
|
380
|
+
await installDependencies(envConfig, repoDir);
|
|
381
|
+
// 6. Write environment variables from GitHub secrets if provided
|
|
382
|
+
const envVarsString = process.env.STAGING_ENVS;
|
|
383
|
+
if (envVarsString) {
|
|
384
|
+
console.log(' Writing environment variables...');
|
|
385
|
+
await writeEnvFile(envConfig, repoDir, 'staging', envVarsString);
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
console.log(' ⚠️ STAGING_ENVS not provided, skipping env file write (using existing .env.staging if present)');
|
|
389
|
+
}
|
|
390
|
+
// 7. Create .env from .env.staging for host commands
|
|
391
|
+
console.log(' Creating .env from .env.staging for host commands...');
|
|
392
|
+
await createEnvFromStaging(envConfig, repoDir);
|
|
393
|
+
return { success: true, message: 'Server ready' };
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
397
|
+
throw new Error(`Failed to prepare server: ${errorMessage}`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Parse DATABASE_URL to extract connection details
|
|
402
|
+
* Format: postgresql://user:password@host:port/database
|
|
403
|
+
*/
|
|
404
|
+
function parseDatabaseUrl(databaseUrl) {
|
|
405
|
+
try {
|
|
406
|
+
const url = new URL(databaseUrl);
|
|
407
|
+
return {
|
|
408
|
+
user: url.username || 'postgres',
|
|
409
|
+
password: url.password || 'password',
|
|
410
|
+
host: url.hostname || 'localhost',
|
|
411
|
+
port: parseInt(url.port || '5432', 10),
|
|
412
|
+
database: url.pathname.slice(1) || 'postgres', // Remove leading /
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
catch {
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Add postgres service to docker-compose.yml for staging
|
|
421
|
+
* Reads DATABASE_URL from .env.staging to configure the postgres service
|
|
422
|
+
* Only applies to staging - production uses RDS
|
|
423
|
+
*/
|
|
424
|
+
async function addPostgresServiceForStaging(envConfig, config) {
|
|
425
|
+
const repoName = config.name ?? 'app';
|
|
426
|
+
const repoDir = `~/.factiii/${repoName}`;
|
|
427
|
+
const isOnServer = process.env.GITHUB_ACTIONS === 'true';
|
|
428
|
+
// Read .env.staging to get DATABASE_URL
|
|
429
|
+
let databaseUrl = null;
|
|
430
|
+
if (isOnServer) {
|
|
431
|
+
const expandedRepoDir = repoDir.replace('~', process.env.HOME ?? '/Users/jon');
|
|
432
|
+
const envFilePath = path.join(expandedRepoDir, '.env.staging');
|
|
433
|
+
if (fs.existsSync(envFilePath)) {
|
|
434
|
+
const envContent = fs.readFileSync(envFilePath, 'utf8');
|
|
435
|
+
const match = envContent.match(/^DATABASE_URL=(.+)$/m);
|
|
436
|
+
if (match) {
|
|
437
|
+
databaseUrl = match[1]?.trim() || null;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
// Remote - read via SSH
|
|
443
|
+
try {
|
|
444
|
+
const envContent = await sshExecCommand(envConfig, `cat ${repoDir}/.env.staging`);
|
|
445
|
+
const match = envContent.match(/^DATABASE_URL=(.+)$/m);
|
|
446
|
+
if (match) {
|
|
447
|
+
databaseUrl = match[1]?.trim() || null;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
451
|
+
// .env.staging might not exist yet
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
if (!databaseUrl) {
|
|
455
|
+
console.log(' ⚠️ DATABASE_URL not found in .env.staging, skipping postgres service');
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
const dbConfig = parseDatabaseUrl(databaseUrl);
|
|
459
|
+
if (!dbConfig) {
|
|
460
|
+
console.log(' ⚠️ Could not parse DATABASE_URL, skipping postgres service');
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const factiiiDir = isOnServer
|
|
464
|
+
? path.join(process.env.HOME ?? '/Users/jon', '.factiii')
|
|
465
|
+
: '~/.factiii';
|
|
466
|
+
const composePath = isOnServer
|
|
467
|
+
? path.join(factiiiDir, 'docker-compose.yml')
|
|
468
|
+
: '~/.factiii/docker-compose.yml';
|
|
469
|
+
// Read docker-compose.yml
|
|
470
|
+
let composeContent;
|
|
471
|
+
if (isOnServer) {
|
|
472
|
+
if (!fs.existsSync(composePath)) {
|
|
473
|
+
console.log(' ⚠️ docker-compose.yml not found, skipping postgres service');
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
composeContent = fs.readFileSync(composePath, 'utf8');
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
composeContent = await sshExecCommand(envConfig, `cat ${composePath}`);
|
|
480
|
+
}
|
|
481
|
+
const compose = js_yaml_1.default.load(composeContent);
|
|
482
|
+
// Check if postgres service already exists
|
|
483
|
+
if (compose.services && 'postgres' in compose.services) {
|
|
484
|
+
console.log(' ℹ️ Postgres service already exists in docker-compose.yml');
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
// Add postgres service
|
|
488
|
+
if (!compose.services) {
|
|
489
|
+
compose.services = {};
|
|
490
|
+
}
|
|
491
|
+
compose.services.postgres = {
|
|
492
|
+
image: 'postgres:16-alpine',
|
|
493
|
+
container_name: 'factiii_postgres',
|
|
494
|
+
restart: 'unless-stopped',
|
|
495
|
+
environment: {
|
|
496
|
+
POSTGRES_USER: dbConfig.user,
|
|
497
|
+
POSTGRES_PASSWORD: dbConfig.password,
|
|
498
|
+
POSTGRES_DB: dbConfig.database,
|
|
499
|
+
},
|
|
500
|
+
ports: [`${dbConfig.port}:5432`],
|
|
501
|
+
volumes: ['postgres_data:/var/lib/postgresql/data'],
|
|
502
|
+
networks: ['factiii'],
|
|
503
|
+
};
|
|
504
|
+
// Add volumes section if it doesn't exist
|
|
505
|
+
if (!compose.volumes) {
|
|
506
|
+
compose.volumes = {};
|
|
507
|
+
}
|
|
508
|
+
compose.volumes.postgres_data = {};
|
|
509
|
+
// Write back
|
|
510
|
+
const updatedContent = js_yaml_1.default.dump(compose, { lineWidth: -1 });
|
|
511
|
+
if (isOnServer) {
|
|
512
|
+
fs.writeFileSync(composePath, updatedContent);
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
await sshExecCommand(envConfig, `cat > ${composePath} << 'EOF'\n${updatedContent}\nEOF`);
|
|
516
|
+
}
|
|
517
|
+
console.log(` ✅ Added postgres service (port ${dbConfig.port}, database: ${dbConfig.database})`);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Update docker-compose.yml to replace build context with staging image tag
|
|
521
|
+
* This is called after buildStagingImage() completes to ensure docker-compose uses the pre-built image
|
|
522
|
+
*/
|
|
523
|
+
async function updateComposeForStagingImage(envConfig, config) {
|
|
524
|
+
const repoName = config.name ?? 'app';
|
|
525
|
+
const serviceName = `${repoName}-staging`;
|
|
526
|
+
const imageTag = `${repoName}:staging`;
|
|
527
|
+
const isOnServer = process.env.GITHUB_ACTIONS === 'true';
|
|
528
|
+
if (isOnServer) {
|
|
529
|
+
// We're on the server - read and update directly
|
|
530
|
+
const factiiiDir = path.join(process.env.HOME ?? '/Users/jon', '.factiii');
|
|
531
|
+
const composePath = path.join(factiiiDir, 'docker-compose.yml');
|
|
532
|
+
if (!fs.existsSync(composePath)) {
|
|
533
|
+
console.log(' ⚠️ docker-compose.yml not found, skipping update');
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
const composeContent = fs.readFileSync(composePath, 'utf8');
|
|
537
|
+
const compose = js_yaml_1.default.load(composeContent);
|
|
538
|
+
if (compose.services && compose.services[serviceName]) {
|
|
539
|
+
// Remove build section and set image to staging tag
|
|
540
|
+
delete compose.services[serviceName].build;
|
|
541
|
+
compose.services[serviceName].image = imageTag;
|
|
542
|
+
}
|
|
543
|
+
// Write back
|
|
544
|
+
const updatedContent = js_yaml_1.default.dump(compose, { lineWidth: -1 });
|
|
545
|
+
fs.writeFileSync(composePath, updatedContent);
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
// We're remote - SSH to update
|
|
549
|
+
const composeContent = await sshExecCommand(envConfig, 'cat ~/.factiii/docker-compose.yml');
|
|
550
|
+
// Parse and update
|
|
551
|
+
const compose = js_yaml_1.default.load(composeContent);
|
|
552
|
+
if (compose.services && compose.services[serviceName]) {
|
|
553
|
+
// Remove build section and set image to staging tag
|
|
554
|
+
delete compose.services[serviceName].build;
|
|
555
|
+
compose.services[serviceName].image = imageTag;
|
|
556
|
+
}
|
|
557
|
+
// Write back to server
|
|
558
|
+
const updatedContent = js_yaml_1.default.dump(compose, { lineWidth: -1 });
|
|
559
|
+
await sshExecCommand(envConfig, `cat > ~/.factiii/docker-compose.yml << 'EOF'\n${updatedContent}\nEOF`);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Deploy to staging environment
|
|
564
|
+
*
|
|
565
|
+
* Note: Docker image building is handled by the pipeline plugin (staging.ts)
|
|
566
|
+
* This method only handles deployment (regenerating docker-compose.yml and starting containers)
|
|
567
|
+
*
|
|
568
|
+
* @param config - Factiii config (supports both v1.x and v2.0.0+)
|
|
569
|
+
* @param environment - Environment name (defaults to 'staging' for backward compatibility)
|
|
570
|
+
*/
|
|
571
|
+
async function deployStaging(config, environment = 'staging') {
|
|
572
|
+
// Get environment config (supports both v1.x and v2.0.0+ formats)
|
|
573
|
+
const environments = (0, config_helpers_js_1.extractEnvironments)(config);
|
|
574
|
+
const envConfig = environments[environment];
|
|
575
|
+
if (!envConfig?.domain) {
|
|
576
|
+
return { success: false, error: `${environment} domain not configured` };
|
|
577
|
+
}
|
|
578
|
+
console.log(` 🚀 Deploying on staging (${envConfig.domain})...`);
|
|
579
|
+
try {
|
|
580
|
+
const repoName = config.name ?? 'app';
|
|
581
|
+
const repoDir = `~/.factiii/${repoName}`;
|
|
582
|
+
// Determine if we're running ON the server or remotely
|
|
583
|
+
// When GITHUB_ACTIONS=true, we're executing on the server itself
|
|
584
|
+
const isOnServer = process.env.GITHUB_ACTIONS === 'true';
|
|
585
|
+
console.log(` 📍 Deployment mode: ${isOnServer ? 'on-server' : 'remote'}`);
|
|
586
|
+
if (isOnServer) {
|
|
587
|
+
// We're on the server - run commands directly
|
|
588
|
+
const factiiiDir = path.join(process.env.HOME ?? '/Users/jon', '.factiii');
|
|
589
|
+
// Step 1: Regenerate unified docker-compose.yml
|
|
590
|
+
console.log(' 🔄 Regenerating unified docker-compose.yml...');
|
|
591
|
+
const repos = (0, index_js_1.scanRepos)();
|
|
592
|
+
const configs = (0, index_js_1.loadConfigs)(repos);
|
|
593
|
+
(0, index_js_1.generateDockerCompose)(configs);
|
|
594
|
+
(0, index_js_1.generateNginx)(configs);
|
|
595
|
+
// Step 1.5: Add postgres service for staging if DATABASE_URL is configured
|
|
596
|
+
console.log(' 🔄 Adding postgres service for staging...');
|
|
597
|
+
await addPostgresServiceForStaging(envConfig, config);
|
|
598
|
+
// Step 2: Update docker-compose.yml to use pre-built staging image
|
|
599
|
+
console.log(' 🔄 Updating docker-compose.yml with staging image tag...');
|
|
600
|
+
await updateComposeForStagingImage(envConfig, config);
|
|
601
|
+
// Step 3: Deploy using unified docker-compose.yml
|
|
602
|
+
const unifiedCompose = path.join(factiiiDir, 'docker-compose.yml');
|
|
603
|
+
if (!fs.existsSync(unifiedCompose)) {
|
|
604
|
+
return {
|
|
605
|
+
success: false,
|
|
606
|
+
error: 'Unified docker-compose.yml not found. Run generate-all.js first.',
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
// Step 4: Start postgres first and wait for it to be ready
|
|
610
|
+
console.log(' 🔄 Starting postgres container...');
|
|
611
|
+
(0, child_process_1.execSync)(`cd ${factiiiDir} && docker compose up -d postgres`, {
|
|
612
|
+
stdio: 'inherit',
|
|
613
|
+
shell: '/bin/bash',
|
|
614
|
+
env: {
|
|
615
|
+
...process.env,
|
|
616
|
+
PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH}`,
|
|
617
|
+
},
|
|
618
|
+
});
|
|
619
|
+
// Wait for postgres to be ready
|
|
620
|
+
console.log(' ⏳ Waiting for postgres to be ready...');
|
|
621
|
+
(0, child_process_1.execSync)(`sleep 3`, { stdio: 'inherit', shell: '/bin/bash' });
|
|
622
|
+
// Step 5: Run Prisma migrations if prisma schema exists
|
|
623
|
+
const expandedRepoDir = repoDir.replace('~', process.env.HOME ?? '/Users/jon');
|
|
624
|
+
const prismaSchemaPath = path.join(expandedRepoDir, config.prisma_schema ?? 'prisma/schema.prisma');
|
|
625
|
+
if (fs.existsSync(prismaSchemaPath)) {
|
|
626
|
+
console.log(' 📦 Running Prisma migrations...');
|
|
627
|
+
try {
|
|
628
|
+
(0, child_process_1.execSync)(`cd ${expandedRepoDir} && npx prisma migrate deploy`, {
|
|
629
|
+
stdio: 'inherit',
|
|
630
|
+
shell: '/bin/bash',
|
|
631
|
+
env: {
|
|
632
|
+
...process.env,
|
|
633
|
+
PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH}`,
|
|
634
|
+
},
|
|
635
|
+
});
|
|
636
|
+
console.log(' ✅ Prisma migrations complete');
|
|
637
|
+
}
|
|
638
|
+
catch (error) {
|
|
639
|
+
console.log(' ⚠️ Prisma migration failed, continuing anyway...');
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
// Step 6: Manage SSL certificates
|
|
643
|
+
console.log(' 🔐 Managing SSL certificates...');
|
|
644
|
+
await runCertbot(envConfig, config);
|
|
645
|
+
await setupCertbotRenewal(envConfig);
|
|
646
|
+
// Step 7: Start all containers
|
|
647
|
+
console.log(' 🚀 Starting containers with unified docker-compose.yml...');
|
|
648
|
+
(0, child_process_1.execSync)(`cd ${factiiiDir} && docker compose up -d`, {
|
|
649
|
+
stdio: 'inherit',
|
|
650
|
+
shell: '/bin/bash',
|
|
651
|
+
env: {
|
|
652
|
+
...process.env,
|
|
653
|
+
PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH}`,
|
|
654
|
+
},
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
// We're remote - SSH to the server
|
|
659
|
+
// Step 1: Regenerate unified docker-compose.yml
|
|
660
|
+
console.log(' 🔄 Regenerating unified docker-compose.yml...');
|
|
661
|
+
const repos = (0, index_js_1.scanRepos)();
|
|
662
|
+
const configs = (0, index_js_1.loadConfigs)(repos);
|
|
663
|
+
(0, index_js_1.generateDockerCompose)(configs);
|
|
664
|
+
(0, index_js_1.generateNginx)(configs);
|
|
665
|
+
// Step 1.5: Add postgres service for staging if DATABASE_URL is configured
|
|
666
|
+
console.log(' 🔄 Adding postgres service for staging...');
|
|
667
|
+
await addPostgresServiceForStaging(envConfig, config);
|
|
668
|
+
// Step 2: Update docker-compose.yml to use pre-built staging image
|
|
669
|
+
console.log(' 🔄 Updating docker-compose.yml with staging image tag...');
|
|
670
|
+
await updateComposeForStagingImage(envConfig, config);
|
|
671
|
+
// Step 3: Start postgres first and wait
|
|
672
|
+
console.log(' 🔄 Starting postgres container on remote server...');
|
|
673
|
+
await sshExecCommand(envConfig, `export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" && \
|
|
674
|
+
cd ~/.factiii && \
|
|
675
|
+
docker compose up -d postgres && \
|
|
676
|
+
sleep 3`);
|
|
677
|
+
// Step 4: Run Prisma migrations if prisma schema exists
|
|
678
|
+
console.log(' 📦 Running Prisma migrations on remote server...');
|
|
679
|
+
await sshExecCommand(envConfig, `export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" && \
|
|
680
|
+
if [ -f ${repoDir}/${config.prisma_schema ?? 'prisma/schema.prisma'} ]; then \
|
|
681
|
+
cd ${repoDir} && npx prisma migrate deploy || echo "⚠️ Prisma migration failed, continuing anyway..."; \
|
|
682
|
+
fi`);
|
|
683
|
+
// Step 5: Manage SSL certificates
|
|
684
|
+
console.log(' 🔐 Managing SSL certificates on remote server...');
|
|
685
|
+
await runCertbot(envConfig, config);
|
|
686
|
+
await setupCertbotRenewal(envConfig);
|
|
687
|
+
// Step 6: Deploy using unified docker-compose.yml
|
|
688
|
+
console.log(' 🚀 Starting containers with unified docker-compose.yml on remote server...');
|
|
689
|
+
await sshExecCommand(envConfig, `export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" && \
|
|
690
|
+
if [ ! -f ~/.factiii/docker-compose.yml ]; then \
|
|
691
|
+
echo "❌ Unified docker-compose.yml not found. Run generate-all.js first." && \
|
|
692
|
+
exit 1; \
|
|
693
|
+
fi && \
|
|
694
|
+
cd ~/.factiii && \
|
|
695
|
+
docker compose up -d`);
|
|
696
|
+
}
|
|
697
|
+
return { success: true, message: 'Staging deployment complete' };
|
|
698
|
+
}
|
|
699
|
+
catch (error) {
|
|
700
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
701
|
+
console.error(` ❌ Deployment failed: ${errorMessage}`);
|
|
702
|
+
return {
|
|
703
|
+
success: false,
|
|
704
|
+
error: errorMessage,
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
//# sourceMappingURL=staging.js.map
|