claude/smbcloud-github-app-k9641p
claude/smbcloud-github-app-k9641p
development
feature/apps
feature/build-release
feature/ci-docs
feature/ci-ruby-gems
feature/cicd
feature/completion
feature/dist-nuget
feature/fix-ci-sdk-pypi-rubygem
feature/fix-clippy-on-stable-channel
feature/fix-deployment-script
feature/github-email
feature/gresiq-v1
feature/project-new-structure
feature/rsync-deploy
feature/ruby-runner
feature/sdk-npm
feature/sdk-workflows
feature/smbcloud-cli-release-npm
feature/smbcloud-deploy
feature/wasm
main
release/v0.7.4
| 1 | # smbCloud GitHub App |
| 2 | |
| 3 | The smbCloud GitHub App connects a GitHub repository to an smbCloud project so |
| 4 | that pushes to the production branch deploy automatically — no `smb deploy` |
| 5 | needed. Deploy results are reported back to GitHub as commit statuses |
| 6 | (`context: smbcloud/deploy`). |
| 7 | |
| 8 | ## How it works |
| 9 | |
| 10 | 1. You install the app on your GitHub account or organization and grant it |
| 11 | access to one or more repositories. |
| 12 | 2. `smb github connect` links a repository (and a production branch) to your |
| 13 | smbCloud project's deploy repo. |
| 14 | 3. On every push, GitHub delivers a `push` webhook to |
| 15 | `https://api.smbcloud.xyz/v1/github/webhook`. The server verifies the |
| 16 | webhook signature, matches the repository, installation, and branch against |
| 17 | a connection, then builds and deploys the project's apps. |
| 18 | 4. The server records a deployment (visible via `smb project deployment`) and |
| 19 | sets a commit status on the pushed SHA: `pending` while building, then |
| 20 | `success` or `failure`. |
| 21 | |
| 22 | The webhook receiver and build pipeline are server-side; this repository ships |
| 23 | the app manifest, the CLI commands, and the client-side API contract. |
| 24 | |
| 25 | ## CLI usage |
| 26 | |
| 27 | All commands accept `--project-id <id>`; without it they use the current |
| 28 | project (`smb project use --id <id>`). The project must have a deploy repo — |
| 29 | run `smb deploy` once to initialize it. |
| 30 | |
| 31 | ```sh |
| 32 | smb github install # open the app installation page, wait for it to complete |
| 33 | smb github connect # pick an installation + repository interactively |
| 34 | smb github connect --repo <owner>/<repo> --branch main # non-interactive, CI-friendly |
| 35 | smb github status # show the current connection |
| 36 | smb github disconnect # remove the connection (asks for confirmation) |
| 37 | ``` |
| 38 | |
| 39 | `smb github install` opens the browser and polls the API until a new |
| 40 | installation appears. A GitHub App's setup URL is fixed app-wide and cannot |
| 41 | point at `localhost`, so a local callback server (as used for OAuth login) is |
| 42 | not possible here — polling is the intended flow. If the poll times out, just |
| 43 | finish the installation in the browser and run `smb github connect`. |
| 44 | |
| 45 | ## Registering the app (operator, one-time) |
| 46 | |
| 47 | The app is registered from [`github-app/manifest.json`](../github-app/manifest.json) |
| 48 | using GitHub's [manifest flow](https://docs.github.com/en/apps/sharing-github-apps/registering-a-github-app-from-a-manifest): |
| 49 | |
| 50 | 1. Serve a small HTML form that POSTs a `manifest` field containing the JSON to |
| 51 | `https://github.com/settings/apps/new?state=<random>` (or |
| 52 | `https://github.com/organizations/<org>/settings/apps/new?state=<random>` |
| 53 | for an org-owned app). |
| 54 | 2. GitHub redirects to the manifest's `redirect_url` with a temporary `code`. |
| 55 | 3. Exchange it within one hour: `POST https://api.github.com/app-manifests/<code>/conversions`. |
| 56 | The response contains the app id, slug, webhook secret, private key, and |
| 57 | OAuth credentials — store these in your server configuration. |
| 58 | 4. If the granted slug differs from `smbcloud`, update `GH_APP_SLUG` in |
| 59 | `crates/smbcloud-networking/src/constants.rs` (the debug build uses a |
| 60 | separate `smbcloud-dev` app whose webhook targets a dev API). |
| 61 | |
| 62 | ### Permissions and events |
| 63 | |
| 64 | | Manifest entry | Why | |
| 65 | | --- | --- | |
| 66 | | `contents: read` | Fetch the repository at the pushed commit to build it. | |
| 67 | | `metadata: read` | Mandatory baseline for every GitHub App; powers repository listing. | |
| 68 | | `statuses: write` | Report deploy state as a commit status (one POST per state change). The Checks API adds no value for v1; upgrading to `checks: write` later is additive. | |
| 69 | | `default_events: ["push"]` | The only event auto-deploy needs. `installation` and `installation_repositories` events are always delivered to App webhooks without subscription — that is how the server tracks installs. | |
| 70 | |
| 71 | ## API contract |
| 72 | |
| 73 | Endpoints the CLI calls (all under the standard authenticated `v1/` API; |
| 74 | implemented server-side): |
| 75 | |
| 76 | | Method | Path | Request | Response | |
| 77 | | --- | --- | --- | --- | |
| 78 | | GET | `v1/github/installations` | — | `[GithubInstallation]` — installations belonging to the authenticated user (correlated via their linked GitHub account) | |
| 79 | | GET | `v1/github/installations/{installation_id}/repositories` | — | `[GithubRepository]` | |
| 80 | | GET | `v1/deploy_repos/{deploy_repo_id}/github_connection` | — | `GithubConnectionStatus` — always `200`, `connected: false` when absent | |
| 81 | | POST | `v1/deploy_repos/{deploy_repo_id}/github_connection` | `GithubConnectionCreate` | `GithubConnection` — upsert; omitted `production_branch` defaults to the repository's default branch | |
| 82 | | DELETE | `v1/deploy_repos/{deploy_repo_id}/github_connection` | — | `null` (`200`, idempotent) | |
| 83 | | POST | `v1/github/webhook` | GitHub webhook payload | server-only; never called by the CLI | |
| 84 | |
| 85 | Response bodies must use `200`/`201` (not `204`). The serde models live in |
| 86 | `crates/smbcloud-model/src/github.rs`; a connection may also arrive embedded in |
| 87 | a `DeployRepo` payload as `github_connection`. |