Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
runs-on: databrickslabs-protected-runner-group
permissions:
contents: write
# id-token: write is required for cosign keyless signing via GitHub OIDC.
# Without it, cosign falls back to interactive auth and the workflow hangs.
id-token: write

steps:
- name: Checkout
Expand Down Expand Up @@ -111,10 +114,52 @@ jobs:
git tag -a "$TAG" -m "Release $TAG"
git push origin "$TAG"

# ----- Supply-chain provenance: SBOM + cosign keyless signature ---------
# Generates a CycloneDX SBOM from the repo (Python + npm package metadata),
# then signs it with cosign using a short-lived OIDC token from GitHub.
# Verifiers can confirm the SBOM came from this workflow at this tag via:
# cosign verify-blob --bundle coda-sbom.cdx.json.cosign.bundle \
# --certificate-identity-regexp 'https://github.com/databrickslabs/coding-agents-databricks-apps/.+' \
# --certificate-oidc-issuer https://token.actions.githubusercontent.com \
# coda-sbom.cdx.json
- name: Generate CycloneDX SBOM
uses: anchore/sbom-action@9f7302141466aa6482940f15371237e9d9f4c34a # v0.20.5
with:
path: .
format: cyclonedx-json
output-file: coda-sbom.cdx.json
# Don't auto-upload; we attach via softprops below for one consistent release.
upload-artifact: false
upload-release-assets: false

- name: Install cosign
uses: sigstore/cosign-installer@d7d6e07ee54d2049ce5cdfc7eed4d6a6ccd80f5b # v3.5.0
with:
cosign-release: v2.4.1

- name: Sign SBOM with cosign (keyless OIDC)
run: |
# --yes auto-confirms the Sigstore transparency log entry (Rekor).
# The resulting bundle contains the signature + certificate + Rekor
# inclusion proof in one self-contained file — easier for downstream
# verifiers than separate .sig/.cert files.
cosign sign-blob --yes \
--bundle coda-sbom.cdx.json.cosign.bundle \
coda-sbom.cdx.json
# Sanity check: verify what we just signed before publishing.
cosign verify-blob \
--bundle coda-sbom.cdx.json.cosign.bundle \
--certificate-identity-regexp 'https://github.com/${{ github.repository }}/.+' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
coda-sbom.cdx.json

- name: Create GitHub Release
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3
with:
tag_name: "${{ steps.version.outputs.TAG }}"
name: "${{ steps.version.outputs.TAG }}"
body: ${{ steps.notes.outputs.NOTES }}
prerelease: ${{ inputs.prerelease }}
files: |
coda-sbom.cdx.json
coda-sbom.cdx.json.cosign.bundle
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,28 @@ This template repo opens that vision up for every Databricks user — no IDE set

Single-user app — the owner is resolved via the app's service principal and Apps API (`app.creator`), with no PAT required at deploy time. Authorization checks `X-Forwarded-Email` against `app.creator`. On first terminal session, the user pastes a short-lived PAT interactively. Tokens auto-rotate every 10 minutes (15-minute lifetime), with old tokens proactively revoked. On restart, the user re-pastes (no persistence by design).

### Verifying release provenance

Each GitHub Release ships with:

- `coda-sbom.cdx.json` — CycloneDX SBOM of every Python + npm dependency (generated by [syft](https://github.com/anchore/syft)).
- `coda-sbom.cdx.json.cosign.bundle` — [Sigstore](https://www.sigstore.dev/) keyless signature bundle (cert + signature + Rekor inclusion proof in one file).

To verify a release came from this repo's release workflow:

```bash
TAG=v1.0.0 # the release you downloaded
gh release download "$TAG" -p 'coda-sbom.cdx.json*'

cosign verify-blob \
--bundle coda-sbom.cdx.json.cosign.bundle \
--certificate-identity-regexp 'https://github.com/databrickslabs/coding-agents-databricks-apps/.+' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
coda-sbom.cdx.json
```

Signing uses GitHub's OIDC token — no long-lived signing keys exist. The signing identity is anchored to the workflow path + tag ref, and a public transparency-log entry is recorded in Rekor.

### Gunicorn

Production uses `workers=1` (PTY state is process-local), `threads=16` (concurrent polling + WebSocket), `gthread` worker class, `timeout=60` (long-lived WebSocket connections).
Expand Down