@mp-lb/arcnet 0.0.0-stage → 0.1.0

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.
Files changed (169) hide show
  1. package/README.md +19 -2
  2. package/dist/addDependency.d.ts +3 -0
  3. package/dist/addDependency.d.ts.map +1 -0
  4. package/dist/addDependency.js +29 -0
  5. package/dist/addDependency.js.map +1 -0
  6. package/dist/apiClient.d.ts +3 -0
  7. package/dist/apiClient.d.ts.map +1 -0
  8. package/dist/apiClient.js +39 -0
  9. package/dist/apiClient.js.map +1 -0
  10. package/dist/checkIdentity.d.ts +3 -0
  11. package/dist/checkIdentity.d.ts.map +1 -0
  12. package/dist/checkIdentity.js +9 -0
  13. package/dist/checkIdentity.js.map +1 -0
  14. package/dist/ciOutputs.d.ts +2 -0
  15. package/dist/ciOutputs.d.ts.map +1 -0
  16. package/dist/ciOutputs.js +31 -0
  17. package/dist/ciOutputs.js.map +1 -0
  18. package/dist/cli.d.ts +3 -0
  19. package/dist/cli.d.ts.map +1 -0
  20. package/dist/cli.js +9 -0
  21. package/dist/cli.js.map +1 -0
  22. package/dist/createCli.d.ts +3 -0
  23. package/dist/createCli.d.ts.map +1 -0
  24. package/dist/createCli.js +83 -0
  25. package/dist/createCli.js.map +1 -0
  26. package/dist/createProject.d.ts +26 -0
  27. package/dist/createProject.d.ts.map +1 -0
  28. package/dist/createProject.js +35 -0
  29. package/dist/createProject.js.map +1 -0
  30. package/dist/createSetupCommand.d.ts +3 -0
  31. package/dist/createSetupCommand.d.ts.map +1 -0
  32. package/dist/createSetupCommand.js +11 -0
  33. package/dist/createSetupCommand.js.map +1 -0
  34. package/dist/deploy.d.ts +3 -0
  35. package/dist/deploy.d.ts.map +1 -0
  36. package/dist/deploy.js +47 -0
  37. package/dist/deploy.js.map +1 -0
  38. package/dist/fail.d.ts +2 -0
  39. package/dist/fail.d.ts.map +1 -0
  40. package/dist/fail.js +4 -0
  41. package/dist/fail.js.map +1 -0
  42. package/dist/index.d.ts +3 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +3 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/inspectReferences.d.ts +3 -0
  47. package/dist/inspectReferences.d.ts.map +1 -0
  48. package/dist/inspectReferences.js +10 -0
  49. package/dist/inspectReferences.js.map +1 -0
  50. package/dist/inspectStaticTree.d.ts +2 -0
  51. package/dist/inspectStaticTree.d.ts.map +1 -0
  52. package/dist/inspectStaticTree.js +17 -0
  53. package/dist/inspectStaticTree.js.map +1 -0
  54. package/dist/packageInfo.d.ts +3 -0
  55. package/dist/packageInfo.d.ts.map +1 -0
  56. package/dist/packageInfo.js +9 -0
  57. package/dist/packageInfo.js.map +1 -0
  58. package/dist/parseSelection.d.ts +3 -0
  59. package/dist/parseSelection.d.ts.map +1 -0
  60. package/dist/parseSelection.js +13 -0
  61. package/dist/parseSelection.js.map +1 -0
  62. package/dist/parseSetupInput.d.ts +16 -0
  63. package/dist/parseSetupInput.d.ts.map +1 -0
  64. package/dist/parseSetupInput.js +34 -0
  65. package/dist/parseSetupInput.js.map +1 -0
  66. package/dist/readSelection.d.ts +15 -0
  67. package/dist/readSelection.d.ts.map +1 -0
  68. package/dist/readSelection.js +36 -0
  69. package/dist/readSelection.js.map +1 -0
  70. package/dist/renderPlan.d.ts +27 -0
  71. package/dist/renderPlan.d.ts.map +1 -0
  72. package/dist/renderPlan.js +25 -0
  73. package/dist/renderPlan.js.map +1 -0
  74. package/dist/renderResult.d.ts +5 -0
  75. package/dist/renderResult.d.ts.map +1 -0
  76. package/dist/renderResult.js +15 -0
  77. package/dist/renderResult.js.map +1 -0
  78. package/dist/resolveRepository.d.ts +2 -0
  79. package/dist/resolveRepository.d.ts.map +1 -0
  80. package/dist/resolveRepository.js +24 -0
  81. package/dist/resolveRepository.js.map +1 -0
  82. package/dist/runProcess.d.ts +2 -0
  83. package/dist/runProcess.d.ts.map +1 -0
  84. package/dist/runProcess.js +16 -0
  85. package/dist/runProcess.js.map +1 -0
  86. package/dist/runTerraform.d.ts +8 -0
  87. package/dist/runTerraform.d.ts.map +1 -0
  88. package/dist/runTerraform.js +111 -0
  89. package/dist/runTerraform.js.map +1 -0
  90. package/dist/runVercel.d.ts +34 -0
  91. package/dist/runVercel.d.ts.map +1 -0
  92. package/dist/runVercel.js +52 -0
  93. package/dist/runVercel.js.map +1 -0
  94. package/dist/safePath.d.ts +2 -0
  95. package/dist/safePath.d.ts.map +1 -0
  96. package/dist/safePath.js +35 -0
  97. package/dist/safePath.js.map +1 -0
  98. package/dist/safeTargetPath.d.ts +2 -0
  99. package/dist/safeTargetPath.d.ts.map +1 -0
  100. package/dist/safeTargetPath.js +29 -0
  101. package/dist/safeTargetPath.js.map +1 -0
  102. package/dist/schemas.d.ts +106 -0
  103. package/dist/schemas.d.ts.map +1 -0
  104. package/dist/schemas.js +85 -0
  105. package/dist/schemas.js.map +1 -0
  106. package/dist/selectNetwork.d.ts +26 -0
  107. package/dist/selectNetwork.d.ts.map +1 -0
  108. package/dist/selectNetwork.js +48 -0
  109. package/dist/selectNetwork.js.map +1 -0
  110. package/dist/setup.d.ts +2 -0
  111. package/dist/setup.d.ts.map +1 -0
  112. package/dist/setup.js +192 -0
  113. package/dist/setup.js.map +1 -0
  114. package/dist/setupReport.d.ts +8 -0
  115. package/dist/setupReport.d.ts.map +1 -0
  116. package/dist/setupReport.js +2 -0
  117. package/dist/setupReport.js.map +1 -0
  118. package/dist/setupVercel.d.ts +9 -0
  119. package/dist/setupVercel.d.ts.map +1 -0
  120. package/dist/setupVercel.js +72 -0
  121. package/dist/setupVercel.js.map +1 -0
  122. package/dist/stageSite.d.ts +3 -0
  123. package/dist/stageSite.d.ts.map +1 -0
  124. package/dist/stageSite.js +31 -0
  125. package/dist/stageSite.js.map +1 -0
  126. package/dist/validateConfig.d.ts +3 -0
  127. package/dist/validateConfig.d.ts.map +1 -0
  128. package/dist/validateConfig.js +17 -0
  129. package/dist/validateConfig.js.map +1 -0
  130. package/docs/public/commands.md +58 -0
  131. package/docs/public/llms-full.txt +79 -0
  132. package/package.json +49 -3
  133. package/src/addDependency.ts +41 -0
  134. package/src/apiClient.ts +51 -0
  135. package/src/checkIdentity.ts +18 -0
  136. package/src/ciOutputs.ts +47 -0
  137. package/src/cli.ts +11 -0
  138. package/src/createCli.ts +118 -0
  139. package/src/createProject.ts +66 -0
  140. package/src/createSetupCommand.ts +16 -0
  141. package/src/deploy.ts +71 -0
  142. package/src/fail.ts +3 -0
  143. package/src/index.ts +2 -0
  144. package/src/inspectReferences.ts +20 -0
  145. package/src/inspectStaticTree.ts +19 -0
  146. package/src/packageInfo.ts +10 -0
  147. package/src/parseSelection.ts +22 -0
  148. package/src/parseSetupInput.ts +40 -0
  149. package/src/readSelection.ts +47 -0
  150. package/src/renderPlan.ts +27 -0
  151. package/src/renderResult.ts +18 -0
  152. package/src/resolveRepository.ts +38 -0
  153. package/src/runProcess.ts +26 -0
  154. package/src/runTerraform.ts +182 -0
  155. package/src/runVercel.ts +77 -0
  156. package/src/safePath.ts +43 -0
  157. package/src/safeTargetPath.ts +32 -0
  158. package/src/schemas.ts +126 -0
  159. package/src/selectNetwork.ts +73 -0
  160. package/src/setup.ts +277 -0
  161. package/src/setupReport.ts +11 -0
  162. package/src/setupVercel.ts +126 -0
  163. package/src/stageSite.ts +54 -0
  164. package/src/validateConfig.ts +22 -0
  165. package/templates/deploy-arc.yaml +73 -0
  166. package/templates/deploy-vercel.yaml +43 -0
  167. package/templates/network.yaml +105 -0
  168. package/templates/vercel-static/main.tf +128 -0
  169. package/templates/vercel-static/module.yaml +51 -0
@@ -0,0 +1,22 @@
1
+ import { fail } from "./fail.js";
2
+ import { safePath } from "./safePath.js";
3
+ import type { VercelConfig } from "./schemas.js";
4
+ import { vercelConfigSchema } from "./schemas.js";
5
+
6
+ export const validateConfig = (input: unknown, root: string): VercelConfig => {
7
+ const config = vercelConfigSchema.parse(input);
8
+ const identities = new Set<string>();
9
+
10
+ for (const site of Object.values(config.sites)) {
11
+ for (const id of [site.projectId, site.projectName].filter(
12
+ (id): id is string => Boolean(id),
13
+ )) {
14
+ if (identities.has(id)) fail("Duplicate Vercel project selection.");
15
+ identities.add(id);
16
+ }
17
+
18
+ safePath(root, site.output);
19
+ }
20
+
21
+ return config;
22
+ };
@@ -0,0 +1,73 @@
1
+ name: Deploy ArcNet project
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ workflow_dispatch:
6
+ permissions:
7
+ contents: read
8
+ concurrency:
9
+ group: arcnet-production
10
+ cancel-in-progress: false
11
+ jobs:
12
+ configuration:
13
+ runs-on: ubuntu-latest
14
+ outputs:
15
+ approved: ${{ steps.config.outputs.approved }}
16
+ provider: ${{ steps.config.outputs.provider }}
17
+ account: ${{ steps.config.outputs.account }}
18
+ registry: ${{ steps.config.outputs.registry }}
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: pnpm/action-setup@v4
22
+ with:
23
+ package_json_file: package.json
24
+ - uses: actions/setup-node@v4
25
+ with:
26
+ node-version: 22
27
+ - run: pnpm install --frozen-lockfile
28
+ - run: pnpm exec arcnet check
29
+ - id: config
30
+ run: pnpm exec arcnet ci
31
+
32
+ deploy:
33
+ needs: configuration
34
+ if: needs.configuration.outputs.approved == 'true' && github.ref == 'refs/heads/main'
35
+ runs-on: ubuntu-latest
36
+ timeout-minutes: 45
37
+ environment: arcnet-production
38
+ permissions:
39
+ contents: read
40
+ id-token: write
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+ - uses: pnpm/action-setup@v4
44
+ with:
45
+ package_json_file: package.json
46
+ - uses: actions/setup-node@v4
47
+ with:
48
+ node-version: 22
49
+ - run: pnpm install --frozen-lockfile
50
+ - uses: google-github-actions/auth@v2
51
+ with:
52
+ workload_identity_provider: ${{ needs.configuration.outputs.provider }}
53
+ service_account: ${{ needs.configuration.outputs.account }}
54
+ - uses: google-github-actions/setup-gcloud@v2
55
+ - run: gcloud auth configure-docker "$REGISTRY" --quiet
56
+ env:
57
+ REGISTRY: ${{ needs.configuration.outputs.registry }}
58
+ - uses: hashicorp/setup-terraform@v3
59
+ with:
60
+ terraform_version: 1.15.6
61
+ terraform_wrapper: false
62
+ - name: Deploy selected services
63
+ run: pnpm exec arcnet deploy
64
+ env:
65
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
66
+ VERCEL_API_TOKEN: ${{ secrets.VERCEL_API_TOKEN }}
67
+ UPSTASH_EMAIL: ${{ secrets.UPSTASH_EMAIL }}
68
+ UPSTASH_API_KEY: ${{ secrets.UPSTASH_API_KEY }}
69
+ MONGODB_ATLAS_PUBLIC_KEY: ${{ secrets.MONGODB_ATLAS_PUBLIC_KEY }}
70
+ MONGODB_ATLAS_PRIVATE_KEY: ${{ secrets.MONGODB_ATLAS_PRIVATE_KEY }}
71
+ ARC_AWS_ACCESS_KEY_ID: ${{ secrets.ARC_AWS_ACCESS_KEY_ID }}
72
+ ARC_AWS_SECRET_ACCESS_KEY: ${{ secrets.ARC_AWS_SECRET_ACCESS_KEY }}
73
+ ARCNET_ENV_JSON: ${{ secrets.ARCNET_ENV_JSON }}
@@ -0,0 +1,43 @@
1
+ name: Deploy ArcNet static sites
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ workflow_dispatch:
6
+ permissions:
7
+ contents: read
8
+ concurrency:
9
+ group: arcnet-vercel-production
10
+ cancel-in-progress: false
11
+ jobs:
12
+ configuration:
13
+ runs-on: ubuntu-latest
14
+ outputs:
15
+ approved: ${{ steps.config.outputs.approved }}
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: 22
21
+ - uses: pnpm/action-setup@v4
22
+ - run: pnpm install --frozen-lockfile
23
+ - run: pnpm exec arcnet check
24
+ - id: config
25
+ run: pnpm exec arcnet ci
26
+
27
+ deploy:
28
+ needs: configuration
29
+ if: needs.configuration.outputs.approved == 'true' && github.ref == 'refs/heads/main'
30
+ environment: arcnet-production
31
+ runs-on: ubuntu-latest
32
+ timeout-minutes: 30
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+ - uses: actions/setup-node@v4
36
+ with:
37
+ node-version: 22
38
+ - uses: pnpm/action-setup@v4
39
+ - run: pnpm install --frozen-lockfile
40
+ - name: Deploy referenced static sites
41
+ run: pnpm exec arcnet deploy
42
+ env:
43
+ VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
@@ -0,0 +1,105 @@
1
+ # Shared network template. Private identifiers are placeholders; operator credentials remain outside Git.
2
+ name: mp-lb
3
+
4
+ # Template vars. gcp-project encodes our convention: one GCP project per code
5
+ # project, mp-lb-<slug> — the per-project inventory, drift and teardown unit.
6
+ region: asia-southeast1
7
+ # AWS region for aws-s3 buckets — matches the legacy manual bucket's region.
8
+ aws-region: ap-southeast-1
9
+ gcp-project: arcnet-{slug}
10
+ network-project: mp-lb-arcnet
11
+ billing-account: REPLACE_BILLING_ACCOUNT
12
+
13
+ dns:
14
+ zone: mp-lb.dev
15
+
16
+ env:
17
+ resolver: dx decrypt --file docs/secrets.json.enc
18
+ public-file: .env.production
19
+
20
+ backend:
21
+ gcs:
22
+ bucket: mp-lb-arcnet-terraform-state
23
+ prefix: terraform/state/{slug}
24
+
25
+ # Image template; arc appends /<service>:<tag>.
26
+ registry: "{region}-docker.pkg.dev/{gcp-project}/{slug}"
27
+
28
+ providers:
29
+ google:
30
+ source: hashicorp/google
31
+ version: "~> 5.0"
32
+ config:
33
+ project: "{gcp-project}"
34
+ region: "{region}"
35
+ # Stamped on every label-supporting resource — the cross-check on top
36
+ # of the per-project boundary.
37
+ default_labels:
38
+ source: arcnet
39
+ project: "{slug}"
40
+ # Send the project as quota project on API requests — required by some
41
+ # APIs (e.g. billingbudgets) when authenticating with user ADC.
42
+ user_project_override: true
43
+ # Quota project must always exist — the per-project one doesn't yet
44
+ # during its own creation. The network project is the stable home.
45
+ billing_project: "{network-project}"
46
+ cloudflare:
47
+ source: cloudflare/cloudflare
48
+ version: "~> 4.0"
49
+ config:
50
+ api_token: "{{cred.CLOUDFLARE_API_TOKEN}}"
51
+ vercel:
52
+ source: vercel/vercel
53
+ version: "~> 1.0"
54
+ config:
55
+ api_token: "{{cred.VERCEL_API_TOKEN}}"
56
+ upstash:
57
+ source: upstash/upstash
58
+ version: "~> 1.0"
59
+ config:
60
+ email: "{{cred.UPSTASH_EMAIL}}"
61
+ api_key: "{{cred.UPSTASH_API_KEY}}"
62
+ mongodbatlas:
63
+ source: mongodb/mongodbatlas
64
+ version: "~> 1.0"
65
+ config:
66
+ public_key: "{{cred.MONGODB_ATLAS_PUBLIC_KEY}}"
67
+ private_key: "{{cred.MONGODB_ATLAS_PRIVATE_KEY}}"
68
+ aws:
69
+ source: hashicorp/aws
70
+ version: "~> 5.0"
71
+ config:
72
+ region: "{aws-region}"
73
+ default_tags:
74
+ tags:
75
+ source: arcnet
76
+ project: "{slug}"
77
+ # Optional static operator keys; unset renders empty and the provider
78
+ # falls back to ambient AWS config (profile/SSO).
79
+ access_key: "{{cred.ARC_AWS_ACCESS_KEY_ID}}"
80
+ secret_key: "{{cred.ARC_AWS_SECRET_ACCESS_KEY}}"
81
+
82
+ # Network facts each module needs; merged under the deploy block's params.
83
+ module-defaults:
84
+ github-ci:
85
+ gcp-project-id: "{gcp-project}"
86
+ state-bucket: mp-lb-arcnet-terraform-state
87
+ network-project: "{network-project}"
88
+ billing-account: "{billing-account}"
89
+ gcp-project:
90
+ project-id: "{gcp-project}"
91
+ billing-account: "{billing-account}"
92
+ gcp-budget:
93
+ billing-account: "{billing-account}"
94
+ gcp-project: "{gcp-project}"
95
+ currency: AUD # the billing account's currency
96
+ project-base:
97
+ region: "{region}"
98
+ cloud-run-web:
99
+ gcp-project-id: "{gcp-project}"
100
+ region: "{region}"
101
+ gce-worker:
102
+ region: "{region}"
103
+ shared-mongo-atlas:
104
+ atlas-project-id: "REPLACE_ATLAS_PROJECT_ID"
105
+ cluster-host: REPLACE_ATLAS_CLUSTER_HOST
@@ -0,0 +1,128 @@
1
+ # A Vercel-hosted static frontend with a custom domain + Cloudflare DNS.
2
+ # The actual upload (vercel deploy of the built output) is this module's
3
+ # post-apply hook (see module.yaml), using the project id output.
4
+
5
+ terraform {
6
+ required_providers {
7
+ vercel = {
8
+ source = "vercel/vercel"
9
+ version = "~> 1.0"
10
+ }
11
+ cloudflare = {
12
+ source = "cloudflare/cloudflare"
13
+ version = "~> 4.0"
14
+ }
15
+ }
16
+ }
17
+
18
+ variable "name" {
19
+ type = string
20
+ }
21
+
22
+ variable "domain" {
23
+ type = string
24
+ }
25
+
26
+ # Cloudflare zone name (passed by arc alongside domain); the module does its
27
+ # own zone lookup and apex detection.
28
+ variable "dns_zone" {
29
+ type = string
30
+ }
31
+
32
+ variable "www_redirect" {
33
+ description = "Also register www.<domain> redirecting to <domain>; default: only for the zone apex"
34
+ type = bool
35
+ default = null
36
+ nullable = true
37
+ }
38
+
39
+ variable "framework" {
40
+ description = "Vercel framework preset (e.g. nextjs); null = static upload"
41
+ type = string
42
+ default = null
43
+ }
44
+
45
+ # The service's resolved deploy env (arc passes it because module.yaml sets
46
+ # service-env). Set on the project so server-side (request-time) code gets it;
47
+ # the build still gets it separately via the upload hook's ARC_SERVICE_ENV.
48
+ variable "env" {
49
+ type = map(string)
50
+ default = {}
51
+ sensitive = true
52
+ }
53
+
54
+ variable "root_directory" {
55
+ description = "Monorepo subdirectory Vercel builds from (framework projects)"
56
+ type = string
57
+ default = null
58
+ }
59
+
60
+ data "cloudflare_zone" "main" {
61
+ name = var.dns_zone
62
+ }
63
+
64
+ locals {
65
+ is_apex = var.domain == var.dns_zone
66
+ www_redirect = coalesce(var.www_redirect, local.is_apex)
67
+ }
68
+
69
+ resource "vercel_project" "main" {
70
+ name = var.name
71
+ framework = var.framework
72
+ root_directory = var.root_directory
73
+ build_command = null
74
+ output_directory = null
75
+ }
76
+
77
+ # One resource per var keeps plans readable and diffs per-var. Keys aren't
78
+ # secret — unwrap them for for_each (resource-level for_each can't iterate a
79
+ # sensitive value); the values stay sensitive.
80
+ resource "vercel_project_environment_variable" "env" {
81
+ for_each = nonsensitive(toset(keys(var.env)))
82
+ project_id = vercel_project.main.id
83
+ key = each.key
84
+ value = var.env[each.key]
85
+ target = ["production"]
86
+ sensitive = true
87
+ }
88
+
89
+ resource "vercel_project_domain" "main" {
90
+ project_id = vercel_project.main.id
91
+ domain = var.domain
92
+ }
93
+
94
+ resource "vercel_project_domain" "www" {
95
+ count = local.www_redirect ? 1 : 0
96
+ project_id = vercel_project.main.id
97
+ domain = "www.${var.domain}"
98
+ redirect = var.domain
99
+ redirect_status_code = 308
100
+
101
+ depends_on = [vercel_project_domain.main]
102
+ }
103
+
104
+ # Apex domains can't CNAME; Vercel publishes a stable A record for them.
105
+ resource "cloudflare_record" "main" {
106
+ allow_overwrite = true
107
+ zone_id = data.cloudflare_zone.main.id
108
+ name = var.domain
109
+ content = local.is_apex ? "76.76.21.21" : "cname.vercel-dns.com"
110
+ type = local.is_apex ? "A" : "CNAME"
111
+ proxied = false
112
+ ttl = 1
113
+ }
114
+
115
+ resource "cloudflare_record" "www" {
116
+ allow_overwrite = true
117
+ count = local.www_redirect ? 1 : 0
118
+ zone_id = data.cloudflare_zone.main.id
119
+ name = "www.${var.domain}"
120
+ content = "cname.vercel-dns.com"
121
+ type = "CNAME"
122
+ proxied = false
123
+ ttl = 1
124
+ }
125
+
126
+ output "project_id" {
127
+ value = vercel_project.main.id
128
+ }
@@ -0,0 +1,51 @@
1
+ # From @mp-lb/zapper 0.21.0; only change: pin Vercel CLI 63.1.2.
2
+ # vercel-static: Terraform owns the Vercel project + DNS; the upload itself
3
+ # is a post-apply hook. Reserved service params it reads: build (optional
4
+ # local build command, run with the service's deploy env), deploy-path (what
5
+ # to upload), local-config (vercel.json path), remote-build (framework
6
+ # projects: build via Vercel's CLI and upload only the build output —
7
+ # uploading the whole monorepo for a remote build overwhelms Vercel's
8
+ # files API).
9
+ defaults:
10
+ name: "{slug}-{service}-arc"
11
+ # Receive the service's resolved deploy env as the `env` Terraform variable
12
+ # (set as Vercel project env vars for request-time code).
13
+ service-env: true
14
+ credentials:
15
+ - name: VERCEL_API_TOKEN
16
+ why: create the Vercel project and upload deploys
17
+ - name: CLOUDFLARE_API_TOKEN
18
+ why: DNS record for the frontend domain
19
+ hooks:
20
+ post-apply:
21
+ - name: vercel upload
22
+ env:
23
+ VERCEL_PROJECT_ID: "{{output.project_id}}"
24
+ ARC_VERCEL_BUILD: "{{params.build}}"
25
+ ARC_VERCEL_DEPLOY_PATH: "{{params.deploy-path}}"
26
+ ARC_VERCEL_LOCAL_CONFIG: "{{params.local-config}}"
27
+ ARC_VERCEL_REMOTE_BUILD: "{{params.remote-build}}"
28
+ run: |
29
+ set -euo pipefail
30
+ VERCEL_ORG_ID="$(curl -fsS -H "Authorization: Bearer ${VERCEL_API_TOKEN}" https://api.vercel.com/v2/user \
31
+ | node -e 'let d="";process.stdin.on("data",c=>d+=c);process.stdin.on("end",()=>console.log(JSON.parse(d).user.id))')"
32
+ export VERCEL_ORG_ID
33
+ if [ -n "${ARC_VERCEL_BUILD}" ]; then
34
+ bash -c "${ARC_VERCEL_BUILD}"
35
+ fi
36
+ if [ "${ARC_VERCEL_REMOTE_BUILD}" = "true" ]; then
37
+ npx -y vercel@63.1.2 pull --yes --environment=production --token="${VERCEL_API_TOKEN}"
38
+ while IFS= read -r kv; do
39
+ if [ -n "${kv}" ]; then
40
+ export "${kv?}"
41
+ fi
42
+ done <<< "$(node -e 'const env=JSON.parse(process.env.ARC_SERVICE_ENV||"{}");for(const [k,v] of Object.entries(env))console.log(`${k}=${v}`)')"
43
+ npx -y vercel@63.1.2 build --prod --token="${VERCEL_API_TOKEN}"
44
+ npx -y vercel@63.1.2 deploy --prebuilt --prod --yes --token="${VERCEL_API_TOKEN}"
45
+ exit 0
46
+ fi
47
+ args=(--prod --yes --token="${VERCEL_API_TOKEN}")
48
+ if [ -n "${ARC_VERCEL_LOCAL_CONFIG}" ]; then
49
+ args+=(--local-config "${ARC_VERCEL_LOCAL_CONFIG}")
50
+ fi
51
+ npx -y vercel@63.1.2 deploy "${ARC_VERCEL_DEPLOY_PATH:-.}" "${args[@]}"