|
1 | 1 | # CI pipeline for the OpenDecree Python SDK. |
2 | 2 | # |
3 | 3 | # Jobs: lint, typecheck, test (matrix: 3.11-3.13), examples → check (alls-green gate) |
4 | | -# Integration job is optional — runs on workflow_dispatch or when |
5 | | -# DECREE_TEST_ADDR secret is set, starting a live server via docker-compose. |
| 4 | +# The examples job compile-checks every example, then starts a live decree |
| 5 | +# server via docker-compose, seeds it, and runs each example end-to-end — |
| 6 | +# so a broken runnable example (e.g. wrong set_many() argument type) fails CI. |
| 7 | +# Integration job is optional — runs on workflow_dispatch with run-integration |
| 8 | +# enabled, exercising the SDK's own integration test suite against a live server. |
6 | 9 |
|
7 | 10 | name: CI |
8 | 11 |
|
@@ -109,31 +112,115 @@ jobs: |
109 | 112 | examples: |
110 | 113 | name: Examples |
111 | 114 | runs-on: ubuntu-latest |
112 | | - timeout-minutes: 10 |
| 115 | + timeout-minutes: 20 |
| 116 | + permissions: |
| 117 | + contents: read |
| 118 | + packages: read |
113 | 119 | steps: |
114 | | - - name: Checkout |
| 120 | + - name: Checkout decree-python |
115 | 121 | uses: actions/checkout@v6 |
116 | 122 | with: |
117 | 123 | persist-credentials: false |
118 | 124 |
|
| 125 | + - name: Checkout decree (for docker-compose + server + CLI) |
| 126 | + uses: actions/checkout@v6 |
| 127 | + with: |
| 128 | + repository: opendecree/decree |
| 129 | + path: decree |
| 130 | + persist-credentials: false |
| 131 | + |
119 | 132 | - name: Set up Python |
120 | 133 | uses: actions/setup-python@v6 |
121 | 134 | with: |
122 | 135 | python-version: "3.12" |
123 | 136 | cache: pip |
124 | 137 | cache-dependency-path: sdk/pyproject.toml |
125 | 138 |
|
126 | | - - name: Install SDK |
127 | | - run: pip install -e sdk/ |
| 139 | + - name: Install SDK with dev dependencies |
| 140 | + run: pip install -e "sdk[dev]" |
128 | 141 |
|
129 | 142 | - name: Compile-check all examples |
| 143 | + # Syntax-only — catches typos but not runtime errors (e.g. iterating |
| 144 | + # a dict where a list[FieldUpdate] is expected). The steps below |
| 145 | + # actually execute the examples against a live server. |
130 | 146 | run: | |
131 | 147 | python -m py_compile examples/quickstart/main.py |
132 | 148 | python -m py_compile examples/async-client/main.py |
133 | 149 | python -m py_compile examples/live-config/main.py |
134 | 150 | python -m py_compile examples/error-handling/main.py |
135 | 151 | python -m py_compile examples/setup.py |
136 | 152 |
|
| 153 | + - name: Log in to ghcr.io |
| 154 | + uses: docker/login-action@v4 |
| 155 | + with: |
| 156 | + registry: ghcr.io |
| 157 | + username: ${{ github.actor }} |
| 158 | + password: ${{ secrets.GITHUB_TOKEN }} |
| 159 | + |
| 160 | + - name: Set up Docker Buildx |
| 161 | + uses: docker/setup-buildx-action@v4 |
| 162 | + with: |
| 163 | + driver: docker-container |
| 164 | + driver-opts: network=host |
| 165 | + |
| 166 | + - name: Build server image |
| 167 | + uses: docker/build-push-action@v7 |
| 168 | + with: |
| 169 | + context: decree |
| 170 | + file: decree/build/Dockerfile |
| 171 | + load: true |
| 172 | + tags: decree-server |
| 173 | + cache-from: | |
| 174 | + type=registry,ref=ghcr.io/opendecree/decree:buildcache |
| 175 | + type=gha,scope=py-examples-server |
| 176 | + cache-to: type=gha,scope=py-examples-server,mode=max |
| 177 | + |
| 178 | + - name: Build tools image (for migrations) |
| 179 | + uses: docker/build-push-action@v7 |
| 180 | + with: |
| 181 | + context: decree/build |
| 182 | + file: decree/build/Dockerfile.tools |
| 183 | + load: true |
| 184 | + tags: decree-tools |
| 185 | + cache-from: | |
| 186 | + type=registry,ref=ghcr.io/opendecree/decree-tools:buildcache |
| 187 | + type=gha,scope=py-examples-tools |
| 188 | + cache-to: type=gha,scope=py-examples-tools,mode=max |
| 189 | + |
| 190 | + - name: Set up Go (for CLI build) |
| 191 | + uses: actions/setup-go@v6 |
| 192 | + with: |
| 193 | + go-version-file: decree/cmd/decree/go.mod |
| 194 | + cache-dependency-path: decree/cmd/decree/go.sum |
| 195 | + |
| 196 | + - name: Build decree CLI |
| 197 | + # examples/setup.py shells out to `decree seed` to provision the |
| 198 | + # schema/tenant/config that the examples read and write. |
| 199 | + run: | |
| 200 | + cd decree/cmd/decree && go build -o "$HOME/go/bin/decree" . |
| 201 | + echo "$HOME/go/bin" >> "$GITHUB_PATH" |
| 202 | +
|
| 203 | + - name: Start decree service |
| 204 | + run: docker compose -f decree/docker-compose.yml up -d --wait service |
| 205 | + env: |
| 206 | + SERVICE_IMAGE: decree-server |
| 207 | + TOOLS_IMAGE: decree-tools |
| 208 | + |
| 209 | + - name: Seed example data |
| 210 | + run: cd examples && python setup.py |
| 211 | + env: |
| 212 | + DECREE_ADDR: "localhost:9090" |
| 213 | + |
| 214 | + - name: Run examples against the live server |
| 215 | + # Executes each runnable example end-to-end (including async-client's |
| 216 | + # set_many call) so a broken example fails CI instead of silently |
| 217 | + # passing a syntax-only check — see opendecree/decree-python#133. |
| 218 | + run: cd examples && make test |
| 219 | + |
| 220 | + - name: Tear down services |
| 221 | + if: always() |
| 222 | + run: docker compose -f decree/docker-compose.yml down -v |
| 223 | + |
137 | 224 | wheel-check: |
138 | 225 | name: Wheel contents |
139 | 226 | runs-on: ubuntu-latest |
|
0 commit comments