Skip to content

Commit 6aa4622

Browse files
committed
fix: use bulk update endpoint when deploying multiple slugs
1 parent 2ccf148 commit 6aa4622

File tree

4 files changed

+395
-25
lines changed

4 files changed

+395
-25
lines changed

api/beta.yaml

Lines changed: 129 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2354,6 +2354,45 @@ paths:
23542354
- Edge Functions
23552355
security:
23562356
- bearer: []
2357+
put:
2358+
operationId: v1-bulk-update-functions
2359+
summary: Bulk update functions
2360+
description: >-
2361+
Bulk update functions. It will create a new function or replace
2362+
existing. The operation is idempotent. NOTE: You will need to manually
2363+
bump the version.
2364+
parameters:
2365+
- name: ref
2366+
required: true
2367+
in: path
2368+
description: Project ref
2369+
schema:
2370+
minLength: 20
2371+
maxLength: 20
2372+
type: string
2373+
requestBody:
2374+
required: true
2375+
content:
2376+
application/json:
2377+
schema:
2378+
type: array
2379+
items:
2380+
$ref: '#/components/schemas/BulkUpdateFunctionBody'
2381+
responses:
2382+
'200':
2383+
description: ''
2384+
content:
2385+
application/json:
2386+
schema:
2387+
$ref: '#/components/schemas/BulkUpdateFunctionResponse'
2388+
'403':
2389+
description: ''
2390+
'500':
2391+
description: Failed to update functions
2392+
tags:
2393+
- Edge Functions
2394+
security:
2395+
- bearer: []
23572396
/v1/projects/{ref}/functions/deploy:
23582397
post:
23592398
operationId: v1-deploy-a-function
@@ -2376,6 +2415,11 @@ paths:
23762415
schema:
23772416
pattern: /^[A-Za-z0-9_-]+$/
23782417
type: string
2418+
- name: bundleOnly
2419+
required: false
2420+
in: query
2421+
schema:
2422+
type: boolean
23792423
requestBody:
23802424
required: true
23812425
content:
@@ -2388,7 +2432,7 @@ paths:
23882432
content:
23892433
application/json:
23902434
schema:
2391-
$ref: '#/components/schemas/FunctionResponse'
2435+
$ref: '#/components/schemas/DeployFunctionResponse'
23922436
'403':
23932437
description: ''
23942438
'500':
@@ -5671,7 +5715,50 @@ components:
56715715
- slug
56725716
- name
56735717
- body
5674-
FunctionMetadata:
5718+
BulkUpdateFunctionBody:
5719+
type: object
5720+
properties:
5721+
version:
5722+
type: integer
5723+
created_at:
5724+
type: integer
5725+
format: int64
5726+
id:
5727+
type: string
5728+
slug:
5729+
type: string
5730+
name:
5731+
type: string
5732+
status:
5733+
enum:
5734+
- ACTIVE
5735+
- REMOVED
5736+
- THROTTLED
5737+
type: string
5738+
verify_jwt:
5739+
type: boolean
5740+
import_map:
5741+
type: boolean
5742+
entrypoint_path:
5743+
type: string
5744+
import_map_path:
5745+
type: string
5746+
required:
5747+
- version
5748+
- id
5749+
- slug
5750+
- name
5751+
- status
5752+
BulkUpdateFunctionResponse:
5753+
type: object
5754+
properties:
5755+
functions:
5756+
type: array
5757+
items:
5758+
$ref: '#/components/schemas/FunctionResponse'
5759+
required:
5760+
- functions
5761+
FunctionDeployMetadata:
56755762
type: object
56765763
properties:
56775764
entrypoint_path:
@@ -5697,10 +5784,49 @@ components:
56975784
type: string
56985785
format: binary
56995786
metadata:
5700-
$ref: '#/components/schemas/FunctionMetadata'
5787+
$ref: '#/components/schemas/FunctionDeployMetadata'
57015788
required:
57025789
- file
57035790
- metadata
5791+
DeployFunctionResponse:
5792+
type: object
5793+
properties:
5794+
version:
5795+
type: integer
5796+
created_at:
5797+
type: integer
5798+
format: int64
5799+
updated_at:
5800+
type: integer
5801+
format: int64
5802+
id:
5803+
type: string
5804+
slug:
5805+
type: string
5806+
name:
5807+
type: string
5808+
status:
5809+
enum:
5810+
- ACTIVE
5811+
- REMOVED
5812+
- THROTTLED
5813+
type: string
5814+
verify_jwt:
5815+
type: boolean
5816+
import_map:
5817+
type: boolean
5818+
entrypoint_path:
5819+
type: string
5820+
import_map_path:
5821+
type: string
5822+
compute_multiplier:
5823+
type: number
5824+
required:
5825+
- version
5826+
- id
5827+
- slug
5828+
- name
5829+
- status
57045830
FunctionSlugResponse:
57055831
type: object
57065832
properties:

internal/functions/deploy/upload.go

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,19 @@ import (
2323
)
2424

2525
func deploy(ctx context.Context, functionConfig config.FunctionConfig, fsys afero.Fs) error {
26+
bundleOnly := len(functionConfig) > 1
27+
var toUpdate []api.BulkUpdateFunctionBody
2628
for slug, fc := range functionConfig {
2729
if !fc.IsEnabled() {
2830
fmt.Fprintln(os.Stderr, "Skipped deploying Function:", slug)
2931
continue
3032
}
3133
fmt.Fprintln(os.Stderr, "Deploying Function:", slug)
32-
meta := api.FunctionMetadata{
34+
param := api.V1DeployAFunctionParams{Slug: &slug}
35+
if bundleOnly {
36+
param.BundleOnly = &bundleOnly
37+
}
38+
meta := api.FunctionDeployMetadata{
3339
Name: &slug,
3440
EntrypointPath: fc.Entrypoint,
3541
ImportMapPath: &fc.ImportMap,
@@ -38,14 +44,34 @@ func deploy(ctx context.Context, functionConfig config.FunctionConfig, fsys afer
3844
if len(fc.StaticFiles) > 0 {
3945
meta.StaticPatterns = &fc.StaticFiles
4046
}
41-
if err := upload(ctx, slug, meta, fsys); err != nil {
47+
resp, err := upload(ctx, param, meta, fsys)
48+
if err != nil {
4249
return err
4350
}
51+
toUpdate = append(toUpdate, api.BulkUpdateFunctionBody{
52+
CreatedAt: resp.CreatedAt,
53+
EntrypointPath: resp.EntrypointPath,
54+
Id: resp.Id,
55+
ImportMap: resp.ImportMap,
56+
ImportMapPath: resp.ImportMapPath,
57+
Name: resp.Name,
58+
Slug: resp.Slug,
59+
Status: api.BulkUpdateFunctionBodyStatus(resp.Status),
60+
VerifyJwt: resp.VerifyJwt,
61+
Version: resp.Version,
62+
})
63+
}
64+
if len(toUpdate) > 1 {
65+
if resp, err := utils.GetSupabase().V1BulkUpdateFunctionsWithResponse(ctx, flags.ProjectRef, toUpdate); err != nil {
66+
return errors.Errorf("failed to bulk update: %w", err)
67+
} else if resp.JSON200 == nil {
68+
return errors.Errorf("unexpected bulk update status %d: %s", resp.StatusCode(), string(resp.Body))
69+
}
4470
}
4571
return nil
4672
}
4773

48-
func upload(ctx context.Context, slug string, meta api.FunctionMetadata, fsys afero.Fs) error {
74+
func upload(ctx context.Context, param api.V1DeployAFunctionParams, meta api.FunctionDeployMetadata, fsys afero.Fs) (*api.DeployFunctionResponse, error) {
4975
body, w := io.Pipe()
5076
form := multipart.NewWriter(w)
5177
errchan := make(chan error, 1)
@@ -57,24 +83,18 @@ func upload(ctx context.Context, slug string, meta api.FunctionMetadata, fsys af
5783
errchan <- err
5884
}
5985
}()
60-
resp, err := utils.GetSupabase().V1DeployAFunctionWithBodyWithResponse(
61-
ctx,
62-
flags.ProjectRef,
63-
&api.V1DeployAFunctionParams{Slug: &slug},
64-
form.FormDataContentType(),
65-
body,
66-
)
86+
resp, err := utils.GetSupabase().V1DeployAFunctionWithBodyWithResponse(ctx, flags.ProjectRef, &param, form.FormDataContentType(), body)
6787
if merr := <-errchan; merr != nil {
68-
return err
88+
return nil, err
6989
} else if err != nil {
70-
return errors.Errorf("failed to deploy function: %w", err)
90+
return nil, errors.Errorf("failed to deploy function: %w", err)
7191
} else if resp.JSON201 == nil {
72-
return errors.Errorf("unexpected deploy status %d: %s", resp.StatusCode(), string(resp.Body))
92+
return nil, errors.Errorf("unexpected deploy status %d: %s", resp.StatusCode(), string(resp.Body))
7393
}
74-
return nil
94+
return resp.JSON201, nil
7595
}
7696

77-
func writeForm(form *multipart.Writer, meta api.FunctionMetadata, fsys afero.Fs) error {
97+
func writeForm(form *multipart.Writer, meta api.FunctionDeployMetadata, fsys afero.Fs) error {
7898
m, err := form.CreateFormField("metadata")
7999
if err != nil {
80100
return errors.Errorf("failed to create metadata: %w", err)

0 commit comments

Comments
 (0)