Skip to content

Commit 428bdd4

Browse files
refactor(cli): make deployment cloud-only (#189)
This simplifies Company Brain deployment around the hosted AWS path only. The CLI no longer exposes local/cloud targets, local Docker setup, local Nango env/config persistence, or local agent-sync targeting; installed users get a cloud deployment workflow that provisions AWS, deploys release artifacts, configures hosted Nango integrations/syncs, and manages agent-sync against the hosted stack. The CI side keeps the immutable-image reuse guard, but now builds only the linux/amd64 images needed by cloud deployment. QEMU and multi-platform image inputs are removed, so repeated Nango builds can be skipped when the submodule-based image tag already exists in GHCR, and local Apple Silicon image support is intentionally out of scope. People who want to run Company Brain locally should clone the repo and use the contributor workflow instead of the installed CLI.
1 parent 925a7f3 commit 428bdd4

51 files changed

Lines changed: 427 additions & 1758 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/build-and-push-docker/action.yml

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,9 @@ inputs:
1717
cache-scope:
1818
description: GitHub Actions cache scope; keep distinct per image to avoid collisions.
1919
required: true
20-
platforms:
21-
description: Comma-separated target platforms.
22-
required: false
23-
default: linux/amd64,linux/arm64
24-
2520
outputs:
2621
image-uri:
27-
description: The immutable image reference that was pushed.
22+
description: The immutable image reference to deploy.
2823
value: ${{ steps.tags.outputs.immutable }}
2924

3025
runs:
@@ -40,18 +35,29 @@ runs:
4035
echo "immutable=$IMAGE_REPOSITORY:$IMAGE_TAG" >> "$GITHUB_OUTPUT"
4136
echo "latest=$IMAGE_REPOSITORY:latest" >> "$GITHUB_OUTPUT"
4237
43-
- name: Set up QEMU
44-
uses: docker/setup-qemu-action@v3
38+
- name: Check for existing image
39+
id: existing-image
40+
shell: bash
41+
env:
42+
IMAGE_URI: ${{ steps.tags.outputs.immutable }}
43+
run: |
44+
if docker manifest inspect "$IMAGE_URI" >/dev/null 2>&1; then
45+
echo "exists=true" >> "$GITHUB_OUTPUT"
46+
echo "Image $IMAGE_URI already exists; skipping build." >> "$GITHUB_STEP_SUMMARY"
47+
else
48+
echo "exists=false" >> "$GITHUB_OUTPUT"
49+
fi
4550
4651
- name: Set up Docker Buildx
52+
if: steps.existing-image.outputs.exists != 'true'
4753
uses: docker/setup-buildx-action@v3
4854

4955
- name: Build and push image
56+
if: steps.existing-image.outputs.exists != 'true'
5057
shell: bash
5158
env:
5259
IMAGE_REPOSITORY: ${{ inputs.image-repository }}
5360
IMAGE_TAG: ${{ inputs.image-tag }}
54-
PLATFORM: ${{ inputs.platforms }}
5561
BUILD_CONTEXT: ${{ inputs.context }}
5662
DOCKERFILE: ${{ inputs.dockerfile }}
5763
CACHE_SCOPE: ${{ inputs.cache-scope }}

.github/workflows/cd.yml

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ permissions:
2121

2222
env:
2323
NO_COLOR: "1"
24-
IMAGE_TAG: sha-${{ github.sha }}
2524

2625
jobs:
2726
deploy-config:
@@ -37,6 +36,9 @@ jobs:
3736
nango_connect_hostname: ${{ steps.config.outputs.nango_connect_hostname }}
3837
brain_hostname: ${{ steps.config.outputs.brain_hostname }}
3938
dozzle_hostname: ${{ steps.config.outputs.dozzle_hostname }}
39+
nango_image_uri: ${{ steps.config.outputs.nango_image_uri }}
40+
brain_image_uri: ${{ steps.config.outputs.brain_image_uri }}
41+
pg_backup_image_uri: ${{ steps.config.outputs.pg_backup_image_uri }}
4042
image_matrix: ${{ steps.config.outputs.image_matrix }}
4143
steps:
4244
- uses: actions/checkout@v6
@@ -71,7 +73,7 @@ jobs:
7173
uses: ./.github/actions/build-and-push-docker
7274
with:
7375
image-repository: ${{ matrix.image.repository }}
74-
image-tag: ${{ env.IMAGE_TAG }}
76+
image-tag: ${{ matrix.image.image_tag }}
7577
context: ${{ matrix.image.context }}
7678
dockerfile: ${{ matrix.image.dockerfile }}
7779
cache-scope: ${{ matrix.image.cache_scope }}
@@ -174,9 +176,9 @@ jobs:
174176
- name: Verify images are public
175177
run: |
176178
infra/deploy/verify_public_images.sh \
177-
ghcr.io/onfabric/company-brain-nango:${{ env.IMAGE_TAG }} \
178-
ghcr.io/onfabric/company-brain-brain:${{ env.IMAGE_TAG }} \
179-
ghcr.io/onfabric/company-brain-pg-backup:${{ env.IMAGE_TAG }}
179+
${{ needs.deploy-config.outputs.nango_image_uri }} \
180+
${{ needs.deploy-config.outputs.brain_image_uri }} \
181+
${{ needs.deploy-config.outputs.pg_backup_image_uri }}
180182
181183
- name: Configure AWS credentials (OIDC)
182184
uses: aws-actions/configure-aws-credentials@v6
@@ -192,9 +194,9 @@ jobs:
192194
DEPLOY_GROUP: ${{ needs.terraform-apply.outputs.deploy_group_tag }}
193195
DATA_VOLUME_ID: ${{ needs.terraform-apply.outputs.data_volume_id }}
194196
ARTIFACTS_BUCKET: ${{ needs.terraform-apply.outputs.artifacts_bucket }}
195-
NANGO_IMAGE_URI: ghcr.io/onfabric/company-brain-nango:${{ env.IMAGE_TAG }}
196-
BRAIN_IMAGE_URI: ghcr.io/onfabric/company-brain-brain:${{ env.IMAGE_TAG }}
197-
PG_BACKUP_IMAGE_URI: ghcr.io/onfabric/company-brain-pg-backup:${{ env.IMAGE_TAG }}
197+
NANGO_IMAGE_URI: ${{ needs.deploy-config.outputs.nango_image_uri }}
198+
BRAIN_IMAGE_URI: ${{ needs.deploy-config.outputs.brain_image_uri }}
199+
PG_BACKUP_IMAGE_URI: ${{ needs.deploy-config.outputs.pg_backup_image_uri }}
198200
ACME_EMAIL: ${{ vars.ACME_EMAIL }}
199201

200202
- name: Deploy on instance via SSM
@@ -249,7 +251,7 @@ jobs:
249251
- uses: ./.github/actions/prepare
250252

251253
- name: Add Nango integrations
252-
run: bun run company-brain --non-interactive add integrations --target cloud --all
254+
run: bun run company-brain --non-interactive add integrations --all
253255

254256
- name: Add Nango syncs
255-
run: bun run company-brain --non-interactive add syncs --target cloud --all
257+
run: bun run company-brain --non-interactive add syncs --all

.github/workflows/release.yml

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ jobs:
2222
outputs:
2323
version: ${{ steps.meta.outputs.version }}
2424
image_matrix: ${{ steps.meta.outputs.image_matrix }}
25+
nango_image_uri: ${{ steps.meta.outputs.nango_image_uri }}
26+
brain_image_uri: ${{ steps.meta.outputs.brain_image_uri }}
27+
pg_backup_image_uri: ${{ steps.meta.outputs.pg_backup_image_uri }}
2528
steps:
2629
- uses: actions/checkout@v6
2730

@@ -31,8 +34,7 @@ jobs:
3134
run: |
3235
version="${{ inputs.version || github.ref_name }}"
3336
echo "version=$version" >> "$GITHUB_OUTPUT"
34-
bun cli/src/scripts/github-deploy-plan.ts github-outputs dev \
35-
| awk -F= '$1 == "image_matrix" { print "image_matrix=" $2 }' >> "$GITHUB_OUTPUT"
37+
bun cli/src/scripts/github-deploy-plan.ts github-outputs dev >> "$GITHUB_OUTPUT"
3638
3739
images:
3840
needs: config
@@ -58,7 +60,7 @@ jobs:
5860
uses: ./.github/actions/build-and-push-docker
5961
with:
6062
image-repository: ${{ matrix.image.repository }}
61-
image-tag: ${{ needs.config.outputs.version }}
63+
image-tag: ${{ matrix.image.image_tag }}
6264
context: ${{ matrix.image.context }}
6365
dockerfile: ${{ matrix.image.dockerfile }}
6466
cache-scope: ${{ matrix.image.cache_scope }}
@@ -75,9 +77,9 @@ jobs:
7577
- name: Verify images are public
7678
run: |
7779
infra/deploy/verify_public_images.sh \
78-
ghcr.io/onfabric/company-brain-nango:${{ needs.config.outputs.version }} \
79-
ghcr.io/onfabric/company-brain-brain:${{ needs.config.outputs.version }} \
80-
ghcr.io/onfabric/company-brain-pg-backup:${{ needs.config.outputs.version }}
80+
${{ needs.config.outputs.nango_image_uri }} \
81+
${{ needs.config.outputs.brain_image_uri }} \
82+
${{ needs.config.outputs.pg_backup_image_uri }}
8183
8284
- uses: ./.github/actions/prepare
8385

@@ -98,6 +100,9 @@ jobs:
98100
- name: Build release manifest and checksums
99101
env:
100102
VERSION: ${{ needs.config.outputs.version }}
103+
NANGO_IMAGE_URI: ${{ needs.config.outputs.nango_image_uri }}
104+
BRAIN_IMAGE_URI: ${{ needs.config.outputs.brain_image_uri }}
105+
PG_BACKUP_IMAGE_URI: ${{ needs.config.outputs.pg_backup_image_uri }}
101106
run: |
102107
runtime_sha=$(shasum -a 256 dist/company-brain-runtime.tar.gz | awk '{print $1}')
103108
integrations_sha=$(shasum -a 256 dist/company-brain-integrations.tar.gz | awk '{print $1}')
@@ -109,9 +114,9 @@ jobs:
109114
"gitSha": "${git_sha}",
110115
"nangoSubmoduleSha": "${nango_sha}",
111116
"images": {
112-
"nango": "ghcr.io/onfabric/company-brain-nango:${VERSION}",
113-
"brain": "ghcr.io/onfabric/company-brain-brain:${VERSION}",
114-
"pgBackup": "ghcr.io/onfabric/company-brain-pg-backup:${VERSION}"
117+
"nango": "${NANGO_IMAGE_URI}",
118+
"brain": "${BRAIN_IMAGE_URI}",
119+
"pgBackup": "${PG_BACKUP_IMAGE_URI}"
115120
},
116121
"assets": {
117122
"runtime": {

README.md

Lines changed: 26 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,61 +4,31 @@ Self-hostable Company Brain experiment: Nango collects records from workplace
44
tools, the brain service normalizes/searches them, and the dashboard lets you
55
inspect what is flowing in.
66

7-
## Local First
7+
## Cloud Deployment
88

9-
Start locally before thinking about AWS, domains, or GitHub Actions.
9+
The installed CLI provisions and operates a hosted Company Brain stack on AWS:
1010

1111
```bash
1212
curl -fsSL https://raw.githubusercontent.com/onfabric/company-brain/main/scripts/install-company-brain-cli.sh | bash
13-
company-brain target local
1413
company-brain setup
1514
```
1615

17-
Contributors can still run the CLI from a checkout:
18-
19-
```bash
20-
git clone --recurse-submodules https://github.com/onfabric/company-brain
21-
cd company-brain
22-
bun install
23-
bun run company-brain target local
24-
bun run company-brain setup
25-
```
26-
27-
Local URLs:
28-
29-
- Brain dashboard: http://localhost:3010/
30-
- Nango dashboard/login and API keys: http://localhost:3003
31-
32-
`setup` with the local target downloads the release assets, generates env
33-
files, starts Docker Compose by default, waits for the stack to become healthy,
34-
then asks for the local Nango dev API key at the end. Use
35-
`company-brain setup --skip-start` if you only want to generate local env files.
36-
Run `company-brain resume` to restart the local stack or save the Nango API key
37-
later.
38-
39-
## Cloud
40-
41-
Provision the hosted Company Brain stack on AWS:
42-
43-
```bash
44-
company-brain target cloud
45-
company-brain setup
46-
```
47-
48-
`setup` with the cloud target provisions AWS infrastructure, deploys the
49-
released containers, verifies DNS/HTTPS, then asks for the hosted Nango dev API
50-
key at the end. If DNS or certificate setup needs a pause, run this after
51-
making the requested changes:
16+
`setup` downloads the release assets, provisions AWS infrastructure, deploys
17+
the released containers, verifies DNS/HTTPS, then asks for the hosted Nango dev
18+
API key. If DNS or certificate setup needs a pause, run this after making the
19+
requested changes:
5220

5321
```bash
5422
company-brain resume
5523
```
5624

57-
Use `--target local` or `--target cloud` on any target-aware command to override
58-
the saved target for one run:
25+
Local deployment is a contributor workflow. Clone the repository if you want to
26+
run Company Brain locally:
5927

6028
```bash
61-
company-brain doctor --target cloud
29+
git clone --recurse-submodules https://github.com/onfabric/company-brain
30+
cd company-brain
31+
bun install
6232
```
6333

6434
## Add Integrations
@@ -67,7 +37,6 @@ Choose and create the Company Brain source integrations you want:
6737

6838
```bash
6939
company-brain add integrations
70-
company-brain add integrations --target cloud
7140
```
7241

7342
The CLI prompts for which source integrations to install and for OAuth app
@@ -76,20 +45,18 @@ key directly:
7645

7746
```bash
7847
company-brain add integrations --nango-secret-key <dev-api-key>
79-
company-brain add integrations --target cloud --nango-secret-key <dev-api-key>
8048
```
8149

82-
Use this callback URL for local OAuth apps:
50+
Use this callback URL for hosted OAuth apps:
8351

8452
```txt
85-
http://localhost:3003/oauth/callback
53+
https://<nango-hostname>/oauth/callback
8654
```
8755

8856
For non-interactive use, pass the integrations explicitly:
8957

9058
```bash
9159
company-brain add integrations --only notion,slack
92-
company-brain add integrations --target cloud --only notion,slack
9360
```
9461

9562
This step only creates the selected source integrations. Syncs are added
@@ -116,14 +83,12 @@ integration you installed:
11683

11784
```bash
11885
company-brain add syncs
119-
company-brain add syncs --target cloud
12086
```
12187

12288
For non-interactive use or manual overrides:
12389

12490
```bash
12591
company-brain add syncs --only notion,slack
126-
company-brain add syncs --target cloud --only notion,slack
12792
```
12893

12994
`--only` overrides the installed-integration list and accepts numbers such as
@@ -143,19 +108,17 @@ Manual sync integrations are:
143108
## Agent Sync
144109

145110
Agent conversations are not installed with the default source integrations. Add
146-
them after the target Company Brain stack is running:
111+
them after the hosted Company Brain stack is running:
147112

148113
```bash
149114
company-brain agent-sync install
150-
company-brain agent-sync install --target cloud
151115
```
152116

153-
The install command checks that the selected target is healthy, makes sure the
117+
The install command checks that the hosted deployment is healthy, makes sure the
154118
Nango dev API key is saved, installs the hidden `agent-conversations`
155-
integration and `conversations` sync in that target Nango, writes the local
156-
sync config, then installs a macOS LaunchAgent that runs
157-
`company-brain agent-sync sync-now --target <target>` on load and on the
158-
configured interval.
119+
integration and `conversations` sync in hosted Nango, writes the local sync
120+
config, then installs a macOS LaunchAgent that runs
121+
`company-brain agent-sync sync-now` on load and on the configured interval.
159122

160123
Manage the schedule with:
161124

@@ -165,30 +128,27 @@ company-brain agent-sync sync-now
165128
company-brain agent-sync uninstall
166129
```
167130

168-
Pass `--target cloud` when agent sync should point at the hosted Company Brain.
169-
170131
## Check Setup
171132

172133
```bash
173134
company-brain doctor
174-
company-brain doctor --target cloud
175135
```
176136

177-
The doctors check service health, saved configuration, Nango API key
178-
configuration, and selected sync configuration.
137+
The doctor checks AWS access, Terraform outputs, DNS, HTTPS, remote Docker
138+
services, and hosted Nango API key configuration.
179139

180140
## CLI
181141

182142
The primary entrypoint is the installed CLI:
183143

184144
```bash
185145
company-brain --help
186-
company-brain target local
187146
company-brain setup
188147
company-brain add integrations
189148
company-brain add syncs
190149
company-brain agent-sync install
191-
company-brain setup --target cloud
150+
company-brain doctor
151+
company-brain destroy
192152
```
193153

194154
Contributors can use `bun run company-brain ...` from a checkout.
@@ -200,10 +160,10 @@ installer. The installed CLI uses the same release manifest lookup unless
200160
`COMPANY_BRAIN_RELEASE_VERSION`, `COMPANY_BRAIN_RELEASE_MANIFEST_URL`, or
201161
`COMPANY_BRAIN_RELEASE_MANIFEST_PATH` is set.
202162

203-
Company Brain release images are published to GHCR for `linux/amd64` and
204-
`linux/arm64`. The release and dev deploy workflows verify that the image tags
205-
are anonymously pullable before publishing deployable artifacts, because local
206-
Docker and EC2 hosts pull them without registry credentials.
163+
Company Brain release images are published to GHCR for `linux/amd64`. The
164+
release and dev deploy workflows verify that the image tags are anonymously
165+
pullable before publishing deployable artifacts, because EC2 hosts pull them
166+
without registry credentials.
207167

208168
## Contributing
209169

0 commit comments

Comments
 (0)