Skip to content

Commit 3d12a01

Browse files
committed
feat(codegen): sample generator
Add a new sub-command for codegen that generates codesamples for each operaion.
1 parent 1460bb8 commit 3d12a01

7 files changed

Lines changed: 911 additions & 26 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: [main]
88

99
env:
10-
GOLANGCI_LINT_VERSION: v2.9.0
10+
GOLANGCI_LINT_VERSION: v2.11.4
1111

1212
permissions:
1313
contents: read
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: Release Code Samples
2+
3+
on:
4+
release:
5+
types:
6+
- published
7+
8+
concurrency:
9+
group: release-code-samples-${{ github.event.release.tag_name }}
10+
cancel-in-progress: true
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
sync-go-code-samples:
17+
name: Sync Go code samples
18+
runs-on: ubuntu-latest
19+
env:
20+
TARGET_REPOSITORY: sumup/sumup-developer
21+
TARGET_BRANCH: automation/go-code-samples
22+
TARGET_FILE: src/codesamples/go.json
23+
steps:
24+
- name: Checkout source code
25+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
26+
with:
27+
ref: refs/tags/${{ github.event.release.tag_name }}
28+
persist-credentials: false
29+
30+
- name: Install Go
31+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
32+
with:
33+
go-version-file: internal/cmd/codegen/go.mod
34+
35+
- name: Create GitHub App token
36+
id: app-token
37+
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
38+
with:
39+
app-id: ${{ secrets.SUMUP_BOT_APP_ID }}
40+
private-key: ${{ secrets.SUMUP_BOT_PRIVATE_KEY }}
41+
owner: sumup
42+
repositories: sumup-developer
43+
44+
- name: Checkout target repository
45+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
46+
with:
47+
repository: ${{ env.TARGET_REPOSITORY }}
48+
ref: main
49+
token: ${{ steps.app-token.outputs.token }}
50+
path: sumup-developer
51+
persist-credentials: true
52+
53+
- name: Get GitHub App User ID
54+
id: get-user-id
55+
env:
56+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
57+
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
58+
59+
- name: Configure git
60+
run: |
61+
git config --global user.name '${{ steps.app-token.outputs.app-slug }}[bot]'
62+
git config --global user.email '${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com'
63+
64+
- name: Prepare target branch
65+
working-directory: sumup-developer
66+
run: git checkout -B "${{ env.TARGET_BRANCH }}" origin/main
67+
68+
- name: Generate Go code samples
69+
working-directory: internal/cmd/codegen
70+
run: |
71+
mkdir -p "../../../sumup-developer/$(dirname "${{ env.TARGET_FILE }}")"
72+
go run . samples ../../../openapi.json > "../../../sumup-developer/${{ env.TARGET_FILE }}"
73+
74+
- name: Commit generated samples
75+
id: commit
76+
working-directory: sumup-developer
77+
run: |
78+
git add "${{ env.TARGET_FILE }}"
79+
if git diff --cached --quiet; then
80+
echo "changed=false" >> "$GITHUB_OUTPUT"
81+
exit 0
82+
fi
83+
84+
git commit -m "chore: update Go code samples for ${{ github.event.release.tag_name }}"
85+
echo "changed=true" >> "$GITHUB_OUTPUT"
86+
87+
- name: Push branch
88+
if: steps.commit.outputs.changed == 'true'
89+
working-directory: sumup-developer
90+
run: git push --force-with-lease origin "${{ env.TARGET_BRANCH }}"
91+
92+
- name: Create or update pull request
93+
if: steps.commit.outputs.changed == 'true'
94+
env:
95+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
96+
run: |
97+
head_ref="sumup:${{ env.TARGET_BRANCH }}"
98+
pr_url="$(gh pr list \
99+
--repo "${{ env.TARGET_REPOSITORY }}" \
100+
--head "$head_ref" \
101+
--base main \
102+
--state open \
103+
--json url \
104+
--jq '.[0].url')"
105+
106+
if [ -n "$pr_url" ]; then
107+
gh pr edit "$pr_url" \
108+
--repo "${{ env.TARGET_REPOSITORY }}" \
109+
--title "chore: update Go code samples" \
110+
--body "Updates \`${{ env.TARGET_FILE }}\` from \`${{ github.repository }}\` release \`${{ github.event.release.tag_name }}\`."
111+
exit 0
112+
fi
113+
114+
gh pr create \
115+
--repo "${{ env.TARGET_REPOSITORY }}" \
116+
--base main \
117+
--head "${{ env.TARGET_BRANCH }}" \
118+
--title "chore: update Go code samples" \
119+
--body "Updates \`${{ env.TARGET_FILE }}\` from \`${{ github.repository }}\` release \`${{ github.event.release.tag_name }}\`."

internal/cmd/codegen/generate.go

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ import (
66
"os"
77
"os/exec"
88

9-
"github.com/pb33f/libopenapi"
109
"github.com/urfave/cli/v2"
11-
12-
"github.com/sumup/sumup-go/internal/cmd/codegen/pkg/builder"
1310
)
1411

1512
func Generate() *cli.Command {
@@ -23,33 +20,13 @@ func Generate() *cli.Command {
2320
return fmt.Errorf("empty argument, path to openapi specs expected")
2421
}
2522

26-
specs := c.Args().First()
27-
2823
if err := os.MkdirAll(out, os.ModePerm); err != nil {
2924
return fmt.Errorf("create output directory %q: %w", out, err)
3025
}
3126

32-
spec, err := os.ReadFile(specs)
33-
if err != nil {
34-
return fmt.Errorf("read specs: %w", err)
35-
}
36-
37-
doc, err := libopenapi.NewDocument(spec)
27+
builder, err := loadBuilder(c.Args().First(), out)
3828
if err != nil {
39-
return fmt.Errorf("load openapi document: %w", err)
40-
}
41-
42-
model, err := doc.BuildV3Model()
43-
if err != nil {
44-
return fmt.Errorf("build openapi v3 model: %w", err)
45-
}
46-
47-
builder := builder.New(builder.Config{
48-
Out: out,
49-
})
50-
51-
if err := builder.Load(&model.Model); err != nil {
52-
return fmt.Errorf("load spec: %w", err)
29+
return err
5330
}
5431

5532
if err := builder.Build(); err != nil {

internal/cmd/codegen/load.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/pb33f/libopenapi"
8+
9+
"github.com/sumup/sumup-go/internal/cmd/codegen/pkg/builder"
10+
)
11+
12+
func loadBuilder(specs, out string) (*builder.Builder, error) {
13+
spec, err := os.ReadFile(specs)
14+
if err != nil {
15+
return nil, fmt.Errorf("read specs: %w", err)
16+
}
17+
18+
doc, err := libopenapi.NewDocument(spec)
19+
if err != nil {
20+
return nil, fmt.Errorf("load openapi document: %w", err)
21+
}
22+
23+
model, err := doc.BuildV3Model()
24+
if err != nil {
25+
return nil, fmt.Errorf("build openapi v3 model: %w", err)
26+
}
27+
28+
b := builder.New(builder.Config{
29+
Out: out,
30+
})
31+
32+
if err := b.Load(&model.Model); err != nil {
33+
return nil, fmt.Errorf("load spec: %w", err)
34+
}
35+
36+
return b, nil
37+
}

internal/cmd/codegen/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func App() *cli.App {
2828
},
2929
Commands: []*cli.Command{
3030
Generate(),
31+
Samples(),
3132
},
3233
}
3334
}

0 commit comments

Comments
 (0)