@sponson/adapters 0.4.0 → 0.5.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.
- package/README.md +1 -1
- package/dist/algolia.d.ts +6 -0
- package/dist/algolia.js +151 -0
- package/dist/algolia.js.map +1 -0
- package/dist/clerk.js +1 -1
- package/dist/clerk.js.map +1 -1
- package/dist/cloudflare.d.ts +25 -0
- package/dist/cloudflare.js +310 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/common.d.ts +2 -6
- package/dist/common.js.map +1 -1
- package/dist/digest.d.ts +46 -0
- package/dist/digest.js +129 -0
- package/dist/digest.js.map +1 -0
- package/dist/digitalocean.d.ts +5 -0
- package/dist/digitalocean.js +243 -0
- package/dist/digitalocean.js.map +1 -0
- package/dist/http-adapter-action.d.ts +63 -0
- package/dist/http-adapter-action.js +369 -0
- package/dist/http-adapter-action.js.map +1 -0
- package/dist/http-adapter-auth.d.ts +88 -0
- package/dist/http-adapter-auth.js +437 -0
- package/dist/http-adapter-auth.js.map +1 -0
- package/dist/http-adapter-client.d.ts +51 -0
- package/dist/http-adapter-client.js +156 -0
- package/dist/http-adapter-client.js.map +1 -0
- package/dist/http-adapter-graphql.d.ts +39 -0
- package/dist/http-adapter-graphql.js +157 -0
- package/dist/http-adapter-graphql.js.map +1 -0
- package/dist/http-adapter-list.d.ts +33 -0
- package/dist/http-adapter-list.js +421 -0
- package/dist/http-adapter-list.js.map +1 -0
- package/dist/http-adapter-resource.d.ts +29 -0
- package/dist/http-adapter-resource.js +462 -0
- package/dist/http-adapter-resource.js.map +1 -0
- package/dist/http-adapter-spec.d.ts +216 -0
- package/dist/http-adapter-spec.js +660 -0
- package/dist/http-adapter-spec.js.map +1 -0
- package/dist/http-adapter.d.ts +16 -0
- package/dist/http-adapter.js +28 -0
- package/dist/http-adapter.js.map +1 -0
- package/dist/http.d.ts +61 -2
- package/dist/http.js +79 -18
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.js +24 -2
- package/dist/index.js.map +1 -1
- package/dist/launchdarkly.d.ts +15 -0
- package/dist/launchdarkly.js +337 -0
- package/dist/launchdarkly.js.map +1 -0
- package/dist/manual.d.ts +13 -0
- package/dist/manual.js +201 -0
- package/dist/manual.js.map +1 -0
- package/dist/neon.js +1 -1
- package/dist/neon.js.map +1 -1
- package/dist/netlify.d.ts +18 -0
- package/dist/netlify.js +436 -0
- package/dist/netlify.js.map +1 -0
- package/dist/planetscale.d.ts +10 -0
- package/dist/planetscale.js +311 -0
- package/dist/planetscale.js.map +1 -0
- package/dist/providers.d.ts +26 -0
- package/dist/providers.js +36 -0
- package/dist/providers.js.map +1 -0
- package/dist/recipes.d.ts +167 -0
- package/dist/recipes.js +246 -0
- package/dist/recipes.js.map +1 -0
- package/dist/secrets.d.ts +44 -0
- package/dist/secrets.js +279 -0
- package/dist/secrets.js.map +1 -1
- package/dist/sigv4.d.ts +56 -0
- package/dist/sigv4.js +118 -0
- package/dist/sigv4.js.map +1 -0
- package/dist/supabase.d.ts +9 -0
- package/dist/supabase.js +385 -0
- package/dist/supabase.js.map +1 -0
- package/dist/vercel.js +1 -1
- package/dist/vercel.js.map +1 -1
- package/dist/xata.d.ts +8 -0
- package/dist/xata.js +142 -0
- package/dist/xata.js.map +1 -0
- package/dist/xml.d.ts +25 -0
- package/dist/xml.js +211 -0
- package/dist/xml.js.map +1 -0
- package/package.json +11 -4
- package/recipes/amplify.yaml +147 -0
- package/recipes/auth0.yaml +178 -0
- package/recipes/azure_swa.yaml +116 -0
- package/recipes/cloud_run.yaml +97 -0
- package/recipes/cloudflare.yaml +108 -0
- package/recipes/cockroachdb.yaml +132 -0
- package/recipes/configcat.yaml +123 -0
- package/recipes/datadog.yaml +136 -0
- package/recipes/firebase.yaml +84 -0
- package/recipes/flagsmith.yaml +98 -0
- package/recipes/fly.yaml +97 -0
- package/recipes/fly_machines.yaml +67 -0
- package/recipes/gcs.yaml +102 -0
- package/recipes/github.yaml +123 -0
- package/recipes/growthbook.yaml +124 -0
- package/recipes/heroku.yaml +98 -0
- package/recipes/honeycomb.yaml +89 -0
- package/recipes/inngest.yaml +97 -0
- package/recipes/kinde.yaml +120 -0
- package/recipes/mongodb_atlas.yaml +119 -0
- package/recipes/okta.yaml +177 -0
- package/recipes/posthog.yaml +127 -0
- package/recipes/postmark.yaml +105 -0
- package/recipes/postmark_server.yaml +93 -0
- package/recipes/prisma.yaml +150 -0
- package/recipes/qstash.yaml +134 -0
- package/recipes/railway.yaml +130 -0
- package/recipes/render.yaml +103 -0
- package/recipes/resend.yaml +130 -0
- package/recipes/s3.yaml +108 -0
- package/recipes/sendgrid.yaml +165 -0
- package/recipes/sentry.yaml +158 -0
- package/recipes/split.yaml +121 -0
- package/recipes/statsig.yaml +124 -0
- package/recipes/stripe.yaml +310 -0
- package/recipes/stytch.yaml +113 -0
- package/recipes/svix.yaml +109 -0
- package/recipes/turso.yaml +98 -0
- package/recipes/unleash.yaml +149 -0
- package/recipes/upstash.yaml +130 -0
- package/recipes/vercel.yaml +116 -0
- package/recipes/workos.yaml +70 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sponson/adapters",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The built-in resource adapters and secret sources for Sponson.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sponson",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"neon",
|
|
13
13
|
"clerk",
|
|
14
14
|
"adapters",
|
|
15
|
-
"secrets"
|
|
15
|
+
"secrets",
|
|
16
|
+
"recipes"
|
|
16
17
|
],
|
|
17
18
|
"license": "Apache-2.0",
|
|
18
19
|
"repository": {
|
|
@@ -33,17 +34,23 @@
|
|
|
33
34
|
}
|
|
34
35
|
},
|
|
35
36
|
"dependencies": {
|
|
36
|
-
"
|
|
37
|
+
"yaml": "^2.8.1",
|
|
38
|
+
"@sponson/core": "0.5.0"
|
|
37
39
|
},
|
|
38
40
|
"devDependencies": {
|
|
39
|
-
"@sponson/sim": "0.
|
|
41
|
+
"@sponson/sim": "0.5.0"
|
|
40
42
|
},
|
|
41
43
|
"files": [
|
|
42
44
|
"dist",
|
|
43
45
|
"!dist/.tsbuildinfo",
|
|
46
|
+
"recipes",
|
|
44
47
|
"README.md",
|
|
45
48
|
"LICENSE"
|
|
46
49
|
],
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public",
|
|
52
|
+
"provenance": true
|
|
53
|
+
},
|
|
47
54
|
"homepage": "https://sponson.mintlify.site",
|
|
48
55
|
"bugs": {
|
|
49
56
|
"url": "https://github.com/MishaBear94/Sponson/issues"
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# AWS Amplify Hosting API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
3
|
+
provider: amplify
|
|
4
|
+
title: AWS Amplify Hosting
|
|
5
|
+
category: deploy
|
|
6
|
+
verified_on: "2026-10-11"
|
|
7
|
+
docs:
|
|
8
|
+
- title: CreateBranch
|
|
9
|
+
url: https://docs.aws.amazon.com/amplify/latest/APIReference/API_CreateBranch.html
|
|
10
|
+
- title: GetBranch
|
|
11
|
+
url: https://docs.aws.amazon.com/amplify/latest/APIReference/API_GetBranch.html
|
|
12
|
+
- title: UpdateBranch
|
|
13
|
+
url: https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateBranch.html
|
|
14
|
+
- title: DeleteBranch
|
|
15
|
+
url: https://docs.aws.amazon.com/amplify/latest/APIReference/API_DeleteBranch.html
|
|
16
|
+
- title: Amplify endpoints and quotas
|
|
17
|
+
url: https://docs.aws.amazon.com/general/latest/gr/amplify.html
|
|
18
|
+
- title: Create a signed AWS API request (SigV4)
|
|
19
|
+
url: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html
|
|
20
|
+
api:
|
|
21
|
+
base_url: https://amplify.us-east-1.amazonaws.com
|
|
22
|
+
base_url_env: AMPLIFY_API_URL
|
|
23
|
+
auth:
|
|
24
|
+
aws_sigv4: { region: us-east-1, service: amplify, access_key_id_env: AWS_ACCESS_KEY_ID, secret_access_key_env: AWS_SECRET_ACCESS_KEY }
|
|
25
|
+
detect:
|
|
26
|
+
files: [amplify.yml]
|
|
27
|
+
starter:
|
|
28
|
+
- op: branch_variable
|
|
29
|
+
values: { branch_name: "${ctx.git.branch}" }
|
|
30
|
+
where:
|
|
31
|
+
app_id: "Amplify console → your app → App settings → General → App ID (`d…`), or `aws amplify list-apps --query 'apps[].appId'`"
|
|
32
|
+
assumptions:
|
|
33
|
+
- id: AM1
|
|
34
|
+
verified: true
|
|
35
|
+
text: "The Amplify API is regional (`https://amplify.<region>.amazonaws.com`) and signed with SigV4 for the service `amplify`. The recipe defaults to `us-east-1`; an app in another region sets `base_url` and `auth` (with its `region`) in the provider block, and temporary credentials (a CI role) add `session_token_env: AWS_SESSION_TOKEN` there."
|
|
36
|
+
source: https://docs.aws.amazon.com/general/latest/gr/amplify.html
|
|
37
|
+
- id: AM2
|
|
38
|
+
verified: true
|
|
39
|
+
text: "`POST /apps/{appId}/branches` (CreateBranch) creates a branch from `branchName` (required) and optional `description`, `stage` (PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST), `enableAutoBuild`, `environmentVariables`, …; it answers 200 with `{ branch }`."
|
|
40
|
+
source: https://docs.aws.amazon.com/amplify/latest/APIReference/API_CreateBranch.html
|
|
41
|
+
- id: AM3
|
|
42
|
+
verified: true
|
|
43
|
+
text: "`GET /apps/{appId}/branches/{branchName}` (GetBranch) answers `{ branch }` with `branchName`, `stage`, `description`, `enableAutoBuild` and `environmentVariables` (a map of string to string)."
|
|
44
|
+
source: https://docs.aws.amazon.com/amplify/latest/APIReference/API_GetBranch.html
|
|
45
|
+
- id: AM4
|
|
46
|
+
verified: true
|
|
47
|
+
text: "`POST /apps/{appId}/branches/{branchName}` (UpdateBranch) takes the same optional fields and answers `{ branch }`; `environmentVariables` is the branch's whole map of variables."
|
|
48
|
+
source: https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateBranch.html
|
|
49
|
+
- id: AM5
|
|
50
|
+
verified: true
|
|
51
|
+
text: "`DELETE /apps/{appId}/branches/{branchName}` (DeleteBranch) deletes a branch; an unknown app or branch is 404 `NotFoundException`."
|
|
52
|
+
source: https://docs.aws.amazon.com/amplify/latest/APIReference/API_DeleteBranch.html
|
|
53
|
+
- id: AM6
|
|
54
|
+
verified: false
|
|
55
|
+
text: "UpdateBranch leaves the fields it is not sent as they are (so the branch op's update does not reset the variables, and the variable op's write does not reset the branch's settings), while an `environmentVariables` it is sent replaces the whole map, as the sim models it (assumption A4 of packages/sim/src/routes/aws.ts)."
|
|
56
|
+
- id: AM7
|
|
57
|
+
verified: false
|
|
58
|
+
text: "A build that ran before a variable was written does not see it: Sponson does not start a new job (StartJob), so order the variable lines before the branch's first build (`enable_auto_build: false` and a CI-started job, or the branch line, then the variables, then the push). The branches Amplify's own pull request previews make are not modelled; this recipe manages a branch the plan names."
|
|
59
|
+
ops:
|
|
60
|
+
branch:
|
|
61
|
+
kind: resource
|
|
62
|
+
title: Branch
|
|
63
|
+
summary: "An Amplify branch named by the plan (the git branch of the pull request, `${ctx.git.branch}`), created with CreateBranch and deleted on destroy. Its `stage`, `description` and auto-build setting are compared: a console edit is drift. Variables on it are `amplify.branch_variable` lines."
|
|
64
|
+
covers: [amplify-branch]
|
|
65
|
+
params:
|
|
66
|
+
app_id:
|
|
67
|
+
type: string
|
|
68
|
+
required: true
|
|
69
|
+
pattern: "^d[a-z0-9]+$"
|
|
70
|
+
description: The Amplify app's id.
|
|
71
|
+
example: d1demo
|
|
72
|
+
branch_name:
|
|
73
|
+
type: string
|
|
74
|
+
required: true
|
|
75
|
+
description: The branch's name, as the repository names it.
|
|
76
|
+
example: "${ctx.scope}"
|
|
77
|
+
stage:
|
|
78
|
+
type: string
|
|
79
|
+
enum: [PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST]
|
|
80
|
+
description: The branch's stage.
|
|
81
|
+
example: PULL_REQUEST
|
|
82
|
+
description:
|
|
83
|
+
type: string
|
|
84
|
+
description: The branch's description.
|
|
85
|
+
example: "Preview of ${ctx.scope}"
|
|
86
|
+
enable_auto_build:
|
|
87
|
+
type: boolean
|
|
88
|
+
description: Build automatically on every push (false lets CI start the build after the variables are written; AM7).
|
|
89
|
+
http:
|
|
90
|
+
read: { path: "/apps/{app_id}/branches/{branch_name}" }
|
|
91
|
+
create:
|
|
92
|
+
path: "/apps/{app_id}/branches"
|
|
93
|
+
body: { branchName: { param: branch_name } }
|
|
94
|
+
update: { method: POST }
|
|
95
|
+
item_path: /branch
|
|
96
|
+
id_path: /branchName
|
|
97
|
+
fields:
|
|
98
|
+
stage: { param: stage }
|
|
99
|
+
description: { param: description }
|
|
100
|
+
enableAutoBuild: { param: enable_auto_build }
|
|
101
|
+
sim:
|
|
102
|
+
id_from: branchName
|
|
103
|
+
live:
|
|
104
|
+
params: { app_id: SPONSON_LIVE_AMPLIFY_APP_ID }
|
|
105
|
+
branch_variable:
|
|
106
|
+
kind: list_item
|
|
107
|
+
title: Branch environment variable
|
|
108
|
+
summary: "One entry of a branch's `environmentVariables`, by read-modify-write of the whole map (UpdateBranch replaces the map it is sent); other variables are left alone, and the branch is locked while Sponson writes it. A branch that is not there yet reads as having no variables, so a plan that also creates the branch shows a create. Builds started before the write do not see it (AM7)."
|
|
109
|
+
covers: [amplify-branch]
|
|
110
|
+
params:
|
|
111
|
+
app_id:
|
|
112
|
+
type: string
|
|
113
|
+
required: true
|
|
114
|
+
pattern: "^d[a-z0-9]+$"
|
|
115
|
+
description: The Amplify app's id.
|
|
116
|
+
example: d1demo
|
|
117
|
+
branch_name:
|
|
118
|
+
type: string
|
|
119
|
+
required: true
|
|
120
|
+
description: The branch's name (a `{ from }` of the `amplify.branch` line orders the two).
|
|
121
|
+
example: "${ctx.scope}"
|
|
122
|
+
name:
|
|
123
|
+
type: string
|
|
124
|
+
required: true
|
|
125
|
+
description: The variable's name.
|
|
126
|
+
example: API_URL
|
|
127
|
+
value:
|
|
128
|
+
type: string
|
|
129
|
+
required: true
|
|
130
|
+
description: The variable's value.
|
|
131
|
+
example: "https://api-${ctx.scope}.example.app"
|
|
132
|
+
http:
|
|
133
|
+
parent: { path: "/apps/{app_id}/branches/{branch_name}", method: POST, send: collection, item_path: /branch, if_missing: empty }
|
|
134
|
+
list_path: /environmentVariables
|
|
135
|
+
shape: map
|
|
136
|
+
item: { param: name }
|
|
137
|
+
value: { param: value }
|
|
138
|
+
sim:
|
|
139
|
+
provider: aws
|
|
140
|
+
base_path: /aws/amplify
|
|
141
|
+
seed: { amplify: { d1demo: { branches: { pr-42: { environmentVariables: { NODE_ENV: production } } } } } }
|
|
142
|
+
present: /amplify/d1demo/branches/pr-42/environmentVariables/API_URL
|
|
143
|
+
drift:
|
|
144
|
+
changed: { amplify.d1demo.pr-42.API_URL: "https://somewhere-else.example" }
|
|
145
|
+
missing: { amplify.d1demo.pr-42.API_URL: delete }
|
|
146
|
+
live:
|
|
147
|
+
params: { app_id: SPONSON_LIVE_AMPLIFY_APP_ID, branch_name: SPONSON_LIVE_AMPLIFY_BRANCH }
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# Auth0 Management API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
3
|
+
provider: auth0
|
|
4
|
+
title: Auth0
|
|
5
|
+
category: auth
|
|
6
|
+
verified_on: "2026-10-11"
|
|
7
|
+
docs:
|
|
8
|
+
- title: Get Management API access tokens for production
|
|
9
|
+
url: https://auth0.com/docs/secure/tokens/access-tokens/management-api-access-tokens/get-management-api-access-tokens-for-production
|
|
10
|
+
- title: Management API v2, get a client
|
|
11
|
+
url: https://auth0.com/docs/api/management/v2/clients/get-clients-by-id
|
|
12
|
+
- title: Management API v2, update a client
|
|
13
|
+
url: https://auth0.com/docs/api/management/v2/clients/patch-clients-by-id
|
|
14
|
+
- title: Auth0 Terraform provider, configuration (conventional variable names)
|
|
15
|
+
url: https://raw.githubusercontent.com/auth0/terraform-provider-auth0/main/docs/index.md
|
|
16
|
+
api:
|
|
17
|
+
base_url_env: AUTH0_API_URL
|
|
18
|
+
auth:
|
|
19
|
+
oauth2_client_credentials:
|
|
20
|
+
token_url: /oauth/token
|
|
21
|
+
token_url_env: AUTH0_TOKEN_URL
|
|
22
|
+
client_id_env: AUTH0_CLIENT_ID
|
|
23
|
+
client_secret_env: AUTH0_CLIENT_SECRET
|
|
24
|
+
audience: /api/v2/
|
|
25
|
+
base_url_example: https://acme.eu.auth0.com/api/v2
|
|
26
|
+
detect:
|
|
27
|
+
deps: [auth0, "@auth0/"]
|
|
28
|
+
env: ["AUTH0_*"]
|
|
29
|
+
starter:
|
|
30
|
+
- op: callback_url
|
|
31
|
+
- op: logout_url
|
|
32
|
+
preview_url: url
|
|
33
|
+
where:
|
|
34
|
+
base_url: "`https://<tenant>.<region>.auth0.com/api/v2`: Auth0 Dashboard → Settings → General → Domain (the canonical domain, not a custom one)"
|
|
35
|
+
client_id: "Auth0 Dashboard → Applications → your application → Settings → Client ID"
|
|
36
|
+
url: "the exact callback URL the app sends as `redirect_uri` on a preview: its URL plus the callback path (a `{ from }` reference cannot carry a path)"
|
|
37
|
+
assumptions:
|
|
38
|
+
- id: AU1
|
|
39
|
+
verified: true
|
|
40
|
+
text: "A machine-to-machine application gets a Management API token from `POST https://<tenant>/oauth/token` (form-encoded `grant_type=client_credentials`, `client_id`, `client_secret`, `audience`); the audience is the Management API's identifier `https://<tenant>/api/v2/`. The answer has `access_token`, `expires_in` (86400 in the example) and `token_type: Bearer`. The recipe writes both as paths, so a plan's `base_url: https://<tenant>/api/v2` names the tenant once."
|
|
41
|
+
source: https://auth0.com/docs/secure/tokens/access-tokens/management-api-access-tokens/get-management-api-access-tokens-for-production
|
|
42
|
+
- id: AU2
|
|
43
|
+
verified: true
|
|
44
|
+
text: "`GET /api/v2/clients/{id}` answers the application with its `callbacks`, `allowed_logout_urls`, `web_origins` and `allowed_origins` arrays, which only a token with `read:clients` (or `read:client_keys`) receives. `fields` with `include_fields=true` limits the answer to the listed fields, so the recipe never reads the client secret."
|
|
45
|
+
source: https://auth0.com/docs/api/management/v2/clients/get-clients-by-id
|
|
46
|
+
- id: AU3
|
|
47
|
+
verified: true
|
|
48
|
+
text: "`PATCH /api/v2/clients/{id}` (scope `update:clients`) updates an application; `callbacks`, `allowed_logout_urls`, `web_origins` and `allowed_origins` are arrays of strings, and the body needs at least one property, so a write sends the one array alone."
|
|
49
|
+
source: https://auth0.com/docs/api/management/v2/clients/patch-clients-by-id
|
|
50
|
+
- id: AU4
|
|
51
|
+
verified: false
|
|
52
|
+
text: "An array sent in a PATCH replaces the stored array whole (it is not merged), so the recipe sends the full list read just before with one URL added or removed. The reference does not say so for these fields."
|
|
53
|
+
- id: AU5
|
|
54
|
+
verified: false
|
|
55
|
+
text: "Updates have no precondition (no ETag or version): the line locks the application (`lockOn`, one lock per tenant and client id, shared by the four ops) against other Sponson runs, and a console edit made between the read and the write can still be lost (the next apply then reports it as drift)."
|
|
56
|
+
- id: AU6
|
|
57
|
+
verified: false
|
|
58
|
+
text: "URLs are stored and read back exactly as written (no trailing slash added or case changed), so a URL identifies its entry."
|
|
59
|
+
- id: AU7
|
|
60
|
+
verified: true
|
|
61
|
+
text: "`AUTH0_CLIENT_ID` and `AUTH0_CLIENT_SECRET` are the variables the Auth0 Terraform provider reads for a machine-to-machine client."
|
|
62
|
+
source: https://raw.githubusercontent.com/auth0/terraform-provider-auth0/main/docs/index.md
|
|
63
|
+
- id: AU8
|
|
64
|
+
verified: false
|
|
65
|
+
text: "The audience stays the tenant's canonical domain when the tenant has a custom domain, so `base_url` names the canonical domain (`<tenant>.<region>.auth0.com`), not the custom one."
|
|
66
|
+
ops:
|
|
67
|
+
callback_url:
|
|
68
|
+
kind: list_item
|
|
69
|
+
title: Application callback URL
|
|
70
|
+
summary: "One URL in an Auth0 application's Allowed Callback URLs (`callbacks`), such as the preview's `/callback`; usually `{ from: <deploy line>.preview_url }` joined with the path in the app. Added by read-modify-write of the list under a lock on the application, removed on destroy; every other URL is left as it is. A URL removed in the Dashboard is drift (`missing`) that the next apply puts back."
|
|
71
|
+
covers: [auth0-callbacks]
|
|
72
|
+
params:
|
|
73
|
+
client_id:
|
|
74
|
+
type: string
|
|
75
|
+
required: true
|
|
76
|
+
description: The application's Client ID.
|
|
77
|
+
example: AbC123dEf456GhI789jKl012MnO345pQ
|
|
78
|
+
url:
|
|
79
|
+
type: string
|
|
80
|
+
required: true
|
|
81
|
+
pattern: "^https?://\\S+$"
|
|
82
|
+
description: "The callback URL, exactly as the application sends it as `redirect_uri`."
|
|
83
|
+
example: "https://${ctx.scope}.preview.example.app/callback"
|
|
84
|
+
http:
|
|
85
|
+
parent:
|
|
86
|
+
path: "/clients/{client_id}"
|
|
87
|
+
read_path: "/clients/{client_id}?fields=callbacks,allowed_logout_urls,web_origins,allowed_origins&include_fields=true"
|
|
88
|
+
list_path: /callbacks
|
|
89
|
+
item: { param: url }
|
|
90
|
+
sim:
|
|
91
|
+
objects:
|
|
92
|
+
"/clients/{client_id}": { callbacks: [https://app.example.com/callback], allowed_logout_urls: [https://app.example.com], web_origins: [https://app.example.com], allowed_origins: [] }
|
|
93
|
+
live:
|
|
94
|
+
params: { client_id: SPONSON_LIVE_AUTH0_APP_CLIENT_ID }
|
|
95
|
+
logout_url:
|
|
96
|
+
kind: list_item
|
|
97
|
+
title: Application allowed logout URL
|
|
98
|
+
summary: "One URL in an Auth0 application's Allowed Logout URLs (`allowed_logout_urls`), where `/v2/logout` may return the user, such as the preview's home page. Read-modify-write of the list under the application's lock; removed on destroy; every other URL is left as it is."
|
|
99
|
+
covers: [auth0-callbacks]
|
|
100
|
+
params:
|
|
101
|
+
client_id:
|
|
102
|
+
type: string
|
|
103
|
+
required: true
|
|
104
|
+
description: The application's Client ID.
|
|
105
|
+
example: AbC123dEf456GhI789jKl012MnO345pQ
|
|
106
|
+
url:
|
|
107
|
+
type: string
|
|
108
|
+
required: true
|
|
109
|
+
pattern: "^https?://\\S+$"
|
|
110
|
+
description: "The URL the application passes as `returnTo` on logout."
|
|
111
|
+
example: "https://${ctx.scope}.preview.example.app"
|
|
112
|
+
http:
|
|
113
|
+
parent:
|
|
114
|
+
path: "/clients/{client_id}"
|
|
115
|
+
read_path: "/clients/{client_id}?fields=callbacks,allowed_logout_urls,web_origins,allowed_origins&include_fields=true"
|
|
116
|
+
list_path: /allowed_logout_urls
|
|
117
|
+
item: { param: url }
|
|
118
|
+
sim:
|
|
119
|
+
objects:
|
|
120
|
+
"/clients/{client_id}": { callbacks: [https://app.example.com/callback], allowed_logout_urls: [https://app.example.com], web_origins: [https://app.example.com], allowed_origins: [] }
|
|
121
|
+
live:
|
|
122
|
+
params: { client_id: SPONSON_LIVE_AUTH0_APP_CLIENT_ID }
|
|
123
|
+
web_origin:
|
|
124
|
+
kind: list_item
|
|
125
|
+
title: Application allowed web origin
|
|
126
|
+
summary: "One origin in an Auth0 application's Allowed Web Origins (`web_origins`), which silent authentication and the SPA SDKs' token refresh need for the preview's origin. Read-modify-write of the list under the application's lock; removed on destroy; every other origin is left as it is."
|
|
127
|
+
covers: [auth0-callbacks]
|
|
128
|
+
params:
|
|
129
|
+
client_id:
|
|
130
|
+
type: string
|
|
131
|
+
required: true
|
|
132
|
+
description: The application's Client ID.
|
|
133
|
+
example: AbC123dEf456GhI789jKl012MnO345pQ
|
|
134
|
+
origin:
|
|
135
|
+
type: string
|
|
136
|
+
required: true
|
|
137
|
+
pattern: "^https?://[^/\\s]+$"
|
|
138
|
+
description: "The origin, scheme and host without a path (`https://pr-42.preview.example.app`)."
|
|
139
|
+
example: "https://${ctx.scope}.preview.example.app"
|
|
140
|
+
http:
|
|
141
|
+
parent:
|
|
142
|
+
path: "/clients/{client_id}"
|
|
143
|
+
read_path: "/clients/{client_id}?fields=callbacks,allowed_logout_urls,web_origins,allowed_origins&include_fields=true"
|
|
144
|
+
list_path: /web_origins
|
|
145
|
+
item: { param: origin }
|
|
146
|
+
sim:
|
|
147
|
+
objects:
|
|
148
|
+
"/clients/{client_id}": { callbacks: [https://app.example.com/callback], allowed_logout_urls: [https://app.example.com], web_origins: [https://app.example.com], allowed_origins: [] }
|
|
149
|
+
live:
|
|
150
|
+
params: { client_id: SPONSON_LIVE_AUTH0_APP_CLIENT_ID }
|
|
151
|
+
allowed_origin:
|
|
152
|
+
kind: list_item
|
|
153
|
+
title: Application allowed origin (CORS)
|
|
154
|
+
summary: "One origin in an Auth0 application's Allowed Origins (CORS, `allowed_origins`), for a preview that calls Auth0 from the browser across origins (embedded login, cross-origin authentication). Read-modify-write of the list under the application's lock; removed on destroy; every other origin is left as it is."
|
|
155
|
+
covers: [auth0-callbacks]
|
|
156
|
+
params:
|
|
157
|
+
client_id:
|
|
158
|
+
type: string
|
|
159
|
+
required: true
|
|
160
|
+
description: The application's Client ID.
|
|
161
|
+
example: AbC123dEf456GhI789jKl012MnO345pQ
|
|
162
|
+
origin:
|
|
163
|
+
type: string
|
|
164
|
+
required: true
|
|
165
|
+
pattern: "^https?://[^/\\s]+$"
|
|
166
|
+
description: "The origin, scheme and host without a path (`https://pr-42.preview.example.app`)."
|
|
167
|
+
example: "https://${ctx.scope}.preview.example.app"
|
|
168
|
+
http:
|
|
169
|
+
parent:
|
|
170
|
+
path: "/clients/{client_id}"
|
|
171
|
+
read_path: "/clients/{client_id}?fields=callbacks,allowed_logout_urls,web_origins,allowed_origins&include_fields=true"
|
|
172
|
+
list_path: /allowed_origins
|
|
173
|
+
item: { param: origin }
|
|
174
|
+
sim:
|
|
175
|
+
objects:
|
|
176
|
+
"/clients/{client_id}": { callbacks: [https://app.example.com/callback], allowed_logout_urls: [https://app.example.com], web_origins: [https://app.example.com], allowed_origins: [] }
|
|
177
|
+
live:
|
|
178
|
+
params: { client_id: SPONSON_LIVE_AUTH0_APP_CLIENT_ID }
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# Azure Static Web Apps (Azure Resource Manager) recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
3
|
+
provider: azure_swa
|
|
4
|
+
title: Azure Static Web Apps
|
|
5
|
+
category: deploy
|
|
6
|
+
verified_on: "2026-10-11"
|
|
7
|
+
docs:
|
|
8
|
+
- title: Static Sites - Create Or Update Static Site Build App Settings
|
|
9
|
+
url: https://learn.microsoft.com/en-us/rest/api/appservice/static-sites/create-or-update-static-site-build-app-settings?view=rest-appservice-2024-04-01
|
|
10
|
+
- title: Static Sites - List Static Site Build App Settings
|
|
11
|
+
url: https://learn.microsoft.com/en-us/rest/api/appservice/static-sites/list-static-site-build-app-settings?view=rest-appservice-2024-04-01
|
|
12
|
+
- title: Static Sites - Get Static Site Builds
|
|
13
|
+
url: https://learn.microsoft.com/en-us/rest/api/appservice/static-sites/get-static-site-builds?view=rest-appservice-2024-04-01
|
|
14
|
+
- title: Preview environments in Azure Static Web Apps
|
|
15
|
+
url: https://learn.microsoft.com/en-us/azure/static-web-apps/preview-environments
|
|
16
|
+
- title: Configure application settings for Azure Static Web Apps
|
|
17
|
+
url: https://learn.microsoft.com/en-us/azure/static-web-apps/application-settings
|
|
18
|
+
- title: az account get-access-token
|
|
19
|
+
url: https://learn.microsoft.com/en-us/cli/azure/account#az-account-get-access-token
|
|
20
|
+
api:
|
|
21
|
+
base_url: https://management.azure.com
|
|
22
|
+
base_url_env: AZURE_SWA_API_URL
|
|
23
|
+
auth: { command: [az, account, get-access-token, --query, accessToken, -o, tsv] }
|
|
24
|
+
detect:
|
|
25
|
+
files: [staticwebapp.config.json]
|
|
26
|
+
env: ["AZURE_STATIC_WEB_APPS_*"]
|
|
27
|
+
starter:
|
|
28
|
+
- op: build_app_setting
|
|
29
|
+
values: { environment: "${ctx.pr.number}" }
|
|
30
|
+
where:
|
|
31
|
+
subscription_id: "`az account show --query id -o tsv`"
|
|
32
|
+
resource_group: "`az staticwebapp show --name <site> --query resourceGroup -o tsv`"
|
|
33
|
+
site: "`az staticwebapp list --query '[].name'`"
|
|
34
|
+
assumptions:
|
|
35
|
+
- id: AZ1
|
|
36
|
+
verified: true
|
|
37
|
+
text: "`PUT https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/staticSites/{name}/builds/{environmentName}/config/appsettings?api-version=2024-04-01` with `{ properties: { <name>: <value>, … } }` sets the app settings of one environment (build) and answers 200 with the same `properties`."
|
|
38
|
+
source: https://learn.microsoft.com/en-us/rest/api/appservice/static-sites/create-or-update-static-site-build-app-settings?view=rest-appservice-2024-04-01
|
|
39
|
+
- id: AZ2
|
|
40
|
+
verified: true
|
|
41
|
+
text: "The settings are read with `POST …/builds/{environmentName}/listAppSettings?api-version=2024-04-01` (no body), which answers a StringDictionary `{ id, properties }`; there is no GET, so the recipe reads with `parent.read_method: POST`."
|
|
42
|
+
source: https://learn.microsoft.com/en-us/rest/api/appservice/static-sites/list-static-site-build-app-settings?view=rest-appservice-2024-04-01
|
|
43
|
+
- id: AZ3
|
|
44
|
+
verified: true
|
|
45
|
+
text: "Each environment is a `builds/{environmentName}` resource: production is `default`, a pull request's preview environment is named by the pull request's number (`builds/12`)."
|
|
46
|
+
source: https://learn.microsoft.com/en-us/rest/api/appservice/static-sites/get-static-site-builds?view=rest-appservice-2024-04-01
|
|
47
|
+
- id: AZ4
|
|
48
|
+
verified: true
|
|
49
|
+
text: "A preview environment exists from the pull request's first deployment and is deleted, with its settings, when the pull request is closed; app settings reach the app's managed API (Functions), not the front-end build."
|
|
50
|
+
source: https://learn.microsoft.com/en-us/azure/static-web-apps/preview-environments
|
|
51
|
+
- id: AZ5
|
|
52
|
+
verified: true
|
|
53
|
+
text: "`az account get-access-token --query accessToken -o tsv` prints an Azure Resource Manager access token for the signed-in account (the default resource is `https://management.azure.com/`), sent as a bearer token."
|
|
54
|
+
source: https://learn.microsoft.com/en-us/cli/azure/account#az-account-get-access-token
|
|
55
|
+
- id: AZ6
|
|
56
|
+
verified: false
|
|
57
|
+
text: "The PUT replaces the whole settings map (a setting it is not sent is removed), so the recipe sends the map as read with the one entry changed (`send: collection`); there is no ETag on this resource, so only Sponson's own writers are serialised (the parent lock), and a setting added in the portal between the read and the write is lost."
|
|
58
|
+
- id: AZ7
|
|
59
|
+
verified: false
|
|
60
|
+
text: "Listing the settings of an environment that does not exist (not deployed yet, or deleted with its pull request) answers 404, which the recipe reads as no settings (`if_missing: empty`): plan shows a create before the first deploy, and destroy after the pull request closed is a no-op. A write before the first deploy fails with that 404; order the line after the deploy."
|
|
61
|
+
ops:
|
|
62
|
+
build_app_setting:
|
|
63
|
+
kind: list_item
|
|
64
|
+
title: App setting of a preview environment
|
|
65
|
+
summary: "One app setting of a Static Web App environment (a pull request's preview environment is named by its number), by read-modify-write of the environment's settings: read with `listAppSettings`, written whole with a PUT. Other settings are left alone and the environment is locked while Sponson writes it. Settings reach the app's managed API, not the front-end build (AZ4); the environment exists only after the PR's first deploy (AZ7)."
|
|
66
|
+
covers: [azure-swa-settings]
|
|
67
|
+
params:
|
|
68
|
+
subscription_id:
|
|
69
|
+
type: string
|
|
70
|
+
required: true
|
|
71
|
+
description: The Azure subscription id.
|
|
72
|
+
example: 00000000-0000-0000-0000-000000000000
|
|
73
|
+
resource_group:
|
|
74
|
+
type: string
|
|
75
|
+
required: true
|
|
76
|
+
description: The resource group of the static web app.
|
|
77
|
+
example: rg-web
|
|
78
|
+
site:
|
|
79
|
+
type: string
|
|
80
|
+
required: true
|
|
81
|
+
description: The static web app's name.
|
|
82
|
+
example: web
|
|
83
|
+
environment:
|
|
84
|
+
type: string
|
|
85
|
+
required: true
|
|
86
|
+
pattern: "^[a-zA-Z0-9]+$"
|
|
87
|
+
description: The environment's name (the pull request's number for its preview environment; `default` is production).
|
|
88
|
+
example: "42"
|
|
89
|
+
name:
|
|
90
|
+
type: string
|
|
91
|
+
required: true
|
|
92
|
+
description: The setting's name.
|
|
93
|
+
example: API_URL
|
|
94
|
+
value:
|
|
95
|
+
type: string
|
|
96
|
+
required: true
|
|
97
|
+
description: The setting's value.
|
|
98
|
+
example: "https://api-${ctx.scope}.example.app"
|
|
99
|
+
http:
|
|
100
|
+
parent:
|
|
101
|
+
path: "/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Web/staticSites/{site}/builds/{environment}/config/appsettings?api-version=2024-04-01"
|
|
102
|
+
read_path: "/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Web/staticSites/{site}/builds/{environment}/listAppSettings?api-version=2024-04-01"
|
|
103
|
+
read_method: POST
|
|
104
|
+
method: PUT
|
|
105
|
+
send: collection
|
|
106
|
+
if_missing: empty
|
|
107
|
+
list_path: /properties
|
|
108
|
+
shape: map
|
|
109
|
+
item: { param: name }
|
|
110
|
+
value: { param: value }
|
|
111
|
+
sim:
|
|
112
|
+
objects:
|
|
113
|
+
"/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Web/staticSites/{site}/builds/{environment}/config/appsettings":
|
|
114
|
+
properties: { SHARED_SETTING: from-the-portal }
|
|
115
|
+
live:
|
|
116
|
+
params: { subscription_id: SPONSON_LIVE_AZURE_SUBSCRIPTION_ID, resource_group: SPONSON_LIVE_AZURE_RESOURCE_GROUP, site: SPONSON_LIVE_AZURE_SWA_SITE, environment: SPONSON_LIVE_AZURE_SWA_ENVIRONMENT }
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# Google Cloud Run Admin API v2 recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
3
|
+
provider: cloud_run
|
|
4
|
+
title: Google Cloud Run
|
|
5
|
+
category: deploy
|
|
6
|
+
verified_on: "2026-10-11"
|
|
7
|
+
docs:
|
|
8
|
+
- title: "REST Resource: projects.locations.services (Service, TrafficTarget)"
|
|
9
|
+
url: https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services
|
|
10
|
+
- title: "Method: projects.locations.services.patch"
|
|
11
|
+
url: https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services/patch
|
|
12
|
+
- title: "Method: projects.locations.services.get"
|
|
13
|
+
url: https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services/get
|
|
14
|
+
- title: Rollbacks, gradual rollouts, and traffic migration (tags)
|
|
15
|
+
url: https://cloud.google.com/run/docs/rollouts-rollbacks-traffic-migration
|
|
16
|
+
- title: gcloud auth print-access-token
|
|
17
|
+
url: https://cloud.google.com/sdk/gcloud/reference/auth/print-access-token
|
|
18
|
+
api:
|
|
19
|
+
base_url: https://run.googleapis.com/v2
|
|
20
|
+
base_url_env: CLOUD_RUN_API_URL
|
|
21
|
+
auth: { command: [gcloud, auth, print-access-token] }
|
|
22
|
+
assumptions:
|
|
23
|
+
- id: CR1
|
|
24
|
+
verified: true
|
|
25
|
+
text: "`GET https://run.googleapis.com/v2/projects/{project}/locations/{location}/services/{service}` answers the Service with its `traffic` list and an `etag`, 'a system-generated fingerprint for this version of the resource' that 'may be used to detect modification conflict during updates'."
|
|
26
|
+
source: https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services
|
|
27
|
+
- id: CR2
|
|
28
|
+
verified: true
|
|
29
|
+
text: "`PATCH https://run.googleapis.com/v2/{service.name}` takes a Service and an optional `updateMask` (fields to update), answers a long-running Operation, and needs the `cloud-platform` scope; the recipe sends `?updateMask=traffic` with `{ traffic, etag }` only, so the revision template is never written."
|
|
30
|
+
source: https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services/patch
|
|
31
|
+
- id: CR3
|
|
32
|
+
verified: true
|
|
33
|
+
text: "A TrafficTarget is `{ type, revision, percent, tag }`; `type: TRAFFIC_TARGET_ALLOCATION_TYPE_REVISION` sends traffic to the named `revision`, `percent` defaults to zero, and `tag` is 'a string to be part of the URI to exclusively reference this target', which is the per-PR URL."
|
|
34
|
+
source: https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services
|
|
35
|
+
- id: CR4
|
|
36
|
+
verified: true
|
|
37
|
+
text: "`gcloud auth print-access-token` prints an OAuth access token for the active account, sent as a bearer token."
|
|
38
|
+
source: https://cloud.google.com/sdk/gcloud/reference/auth/print-access-token
|
|
39
|
+
- id: CR5
|
|
40
|
+
verified: false
|
|
41
|
+
text: "A patch whose `etag` no longer matches (a deploy changed the service after the read) is refused (409 ABORTED or 412) rather than applied: the line fails and the next apply reads again, so a concurrent `gcloud run deploy` is never overwritten. Sponson's own writers are serialised by the parent lock."
|
|
42
|
+
- id: CR6
|
|
43
|
+
verified: false
|
|
44
|
+
text: "The Service answered right after the patch's Operation is accepted already shows the new `traffic` (the desired state), so the re-read that confirms the write sees the tag; `percent` 0 is left out of the answer and `type` and `revision` are answered as sent."
|
|
45
|
+
- id: CR7
|
|
46
|
+
verified: false
|
|
47
|
+
text: "The revision a tag points to exists before the line applies: the PR's deploy creates it (`gcloud run deploy --no-traffic --revision-suffix <scope>` gives `<service>-<scope>`). Its environment variables are part of that revision, set by the deploy, not by this recipe; a deploy that tags (`--tag`) itself conflicts with this line's tag."
|
|
48
|
+
ops:
|
|
49
|
+
traffic_tag:
|
|
50
|
+
kind: list_item
|
|
51
|
+
title: Traffic tag of a revision
|
|
52
|
+
summary: "A tag (`pr-42`) in a service's `traffic` list pointing at the PR's revision with no traffic share, which gives the revision its own URL (`https://pr-42---<service>-<hash>.a.run.app`). Read-modify-write of `traffic` only (`updateMask=traffic`), sent with the service's `etag` so a concurrent deploy makes the write fail instead of being overwritten (CR5); other tags and the traffic split are left alone, and destroy removes only this tag. The revision itself, and its environment variables, are the deploy's (CR7)."
|
|
53
|
+
covers: []
|
|
54
|
+
params:
|
|
55
|
+
project:
|
|
56
|
+
type: string
|
|
57
|
+
required: true
|
|
58
|
+
description: The Google Cloud project id.
|
|
59
|
+
example: demo-project
|
|
60
|
+
region:
|
|
61
|
+
type: string
|
|
62
|
+
required: true
|
|
63
|
+
description: The service's region.
|
|
64
|
+
example: us-central1
|
|
65
|
+
service:
|
|
66
|
+
type: string
|
|
67
|
+
required: true
|
|
68
|
+
description: The Cloud Run service's name.
|
|
69
|
+
example: web
|
|
70
|
+
tag:
|
|
71
|
+
type: string
|
|
72
|
+
required: true
|
|
73
|
+
pattern: "^[a-z][a-z0-9-]*$"
|
|
74
|
+
description: The tag, the prefix of the revision's own URL.
|
|
75
|
+
example: "${ctx.scope}"
|
|
76
|
+
revision:
|
|
77
|
+
type: string
|
|
78
|
+
required: true
|
|
79
|
+
description: The revision the tag points to (made by the PR's deploy).
|
|
80
|
+
example: "web-${ctx.scope}"
|
|
81
|
+
http:
|
|
82
|
+
parent:
|
|
83
|
+
path: "/projects/{project}/locations/{region}/services/{service}?updateMask=traffic"
|
|
84
|
+
read_path: "/projects/{project}/locations/{region}/services/{service}"
|
|
85
|
+
method: PATCH
|
|
86
|
+
send: [etag]
|
|
87
|
+
list_path: /traffic
|
|
88
|
+
key_field: tag
|
|
89
|
+
item: { tag: { param: tag }, revision: { param: revision }, type: TRAFFIC_TARGET_ALLOCATION_TYPE_REVISION }
|
|
90
|
+
sim:
|
|
91
|
+
objects:
|
|
92
|
+
"/projects/{project}/locations/{region}/services/{service}":
|
|
93
|
+
name: projects/demo-project/locations/us-central1/services/web
|
|
94
|
+
etag: '"sim-etag-1"'
|
|
95
|
+
traffic: [{ type: TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST, percent: 100 }]
|
|
96
|
+
live:
|
|
97
|
+
params: { project: SPONSON_LIVE_GCP_PROJECT, region: SPONSON_LIVE_CLOUD_RUN_REGION, service: SPONSON_LIVE_CLOUD_RUN_SERVICE, revision: SPONSON_LIVE_CLOUD_RUN_REVISION }
|