Skip to content
Merged
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
32 changes: 32 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Keep the build context small.
.git
.github
.claude
.claude-plugin
.tmp
.venv
venv
.vscode
.idea
node_modules
**/__pycache__
**/*.pyc
*.egg-info
dist
build
brain
Leads
docs
marketing
examples
tests
cloud
hooks
memory
sdk
gradata-install
packages
CHANGELOG.md
CONTRIBUTING.md
CREDITS.md
mkdocs.yml
131 changes: 131 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
name: Docker Publish

# Trigger on Docker image tags: docker-v0.5.0, docker-v0.5.1rc1, etc.
# Push a build to GHCR on tag; validate-only on non-tag push/PR.
on:
push:
branches: [main]
tags:
- "docker-v*"
pull_request:
branches: [main]

concurrency:
group: docker-publish-${{ github.ref }}
cancel-in-progress: false

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/daemon

jobs:
build:
name: Build image (validate)
runs-on: ubuntu-latest
outputs:
version: ${{ steps.meta.outputs.version }}
is_prerelease: ${{ steps.meta.outputs.is_prerelease }}
is_tag: ${{ steps.meta.outputs.is_tag }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Derive version from tag
id: meta
run: |
REF="${GITHUB_REF}"
if [[ "${REF}" == refs/tags/docker-v* ]]; then
TAG="${REF#refs/tags/}"
VERSION="${TAG#docker-v}"
echo "is_tag=true" >> "$GITHUB_OUTPUT"
else
VERSION="dev-${GITHUB_SHA::7}"
echo "is_tag=false" >> "$GITHUB_OUTPUT"
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
if [[ "${VERSION}" =~ (rc|a|b|dev|alpha|beta) ]]; then
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
else
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
fi
echo "Ref: ${REF}"
echo "Version: ${VERSION}"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build image (no push)
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: false
load: true
tags: gradata/daemon:validate-${{ steps.meta.outputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Smoke test — --version
run: |
docker run --rm gradata/daemon:validate-${{ steps.meta.outputs.version }} --version

- name: Report image size
run: |
SIZE=$(docker image inspect gradata/daemon:validate-${{ steps.meta.outputs.version }} --format '{{.Size}}')
MB=$(( SIZE / 1024 / 1024 ))
echo "Image size: ${MB} MB"
if [ "${MB}" -gt 200 ]; then
echo "::warning::Image size ${MB} MB exceeds 200 MB target"
fi

publish:
name: Publish to GHCR
needs: build
if: needs.build.outputs.is_tag == 'true'
runs-on: ubuntu-latest

permissions:
contents: read
packages: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Compute tags
id: tags
run: |
VERSION="${{ needs.build.outputs.version }}"
IS_PRE="${{ needs.build.outputs.is_prerelease }}"
BASE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
TAGS="${BASE}:${VERSION}"
if [ "${IS_PRE}" = "false" ]; then
TAGS="${TAGS},${BASE}:latest"
fi
echo "tags=${TAGS}" >> "$GITHUB_OUTPUT"
echo "Publishing tags: ${TAGS}"

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.tags.outputs.tags }}
labels: |
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.version=${{ needs.build.outputs.version }}
org.opencontainers.image.licenses=AGPL-3.0-or-later
cache-from: type=gha
cache-to: type=gha,mode=max
156 changes: 156 additions & 0 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
name: npm Publish

# Trigger on npm package tags: npm-v0.1.0, npm-v0.1.1-rc.1, etc.
# Pre-release versions (rc/alpha/beta/dev) publish with --tag next.
on:
push:
tags:
- "npm-v*"

concurrency:
group: npm-publish-${{ github.ref }}
cancel-in-progress: false

jobs:
build:
name: Build and test
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/npm
outputs:
version: ${{ steps.meta.outputs.version }}
is_prerelease: ${{ steps.meta.outputs.is_prerelease }}
already_published: ${{ steps.check.outputs.already_published }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"

- name: Derive version from tag
id: meta
run: |
TAG="${GITHUB_REF#refs/tags/}"
VERSION="${TAG#npm-v}"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
if [[ "${VERSION}" =~ (rc|a|b|dev|alpha|beta) ]]; then
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
else
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
fi
echo "Tag: ${TAG}"
echo "Version: ${VERSION}"

- name: Verify tag matches package.json version
run: |
PKG_VERSION=$(node -p "require('./package.json').version")
TAG_VERSION="${{ steps.meta.outputs.version }}"
if [ "${PKG_VERSION}" != "${TAG_VERSION}" ]; then
echo "::error::Tag version (${TAG_VERSION}) does not match packages/npm/package.json version (${PKG_VERSION})."
echo "::error::Bump package.json to ${TAG_VERSION} or retag."
exit 1
fi
echo "Version match confirmed: ${PKG_VERSION}"

- name: Check if version already exists on npm
id: check
run: |
VERSION="${{ steps.meta.outputs.version }}"
echo "Querying npm registry for @gradata/cli@${VERSION}"
HTTP_STATUS=$(curl -s -o /tmp/npm.json -w "%{http_code}" "https://registry.npmjs.org/@gradata/cli/${VERSION}" || echo "000")
if [ "${HTTP_STATUS}" = "404" ]; then
echo "Version not yet published."
echo "already_published=false" >> "$GITHUB_OUTPUT"
elif [ "${HTTP_STATUS}" = "200" ]; then
echo "::warning::@gradata/cli@${VERSION} is already published. Skipping publish step."
echo "already_published=true" >> "$GITHUB_OUTPUT"
else
echo "::warning::Unexpected HTTP ${HTTP_STATUS} from npm registry. Proceeding."
echo "already_published=false" >> "$GITHUB_OUTPUT"
fi

- name: Install
if: steps.check.outputs.already_published != 'true'
run: npm ci || npm install --no-audit --no-fund

- name: Typecheck
if: steps.check.outputs.already_published != 'true'
run: npm run typecheck

- name: Test
if: steps.check.outputs.already_published != 'true'
run: npm test

- name: Build
if: steps.check.outputs.already_published != 'true'
run: npm run build

- name: Pack (sanity check)
if: steps.check.outputs.already_published != 'true'
run: npm pack --dry-run

- name: Upload tarball artefact
if: steps.check.outputs.already_published != 'true'
uses: actions/upload-artifact@v4
with:
name: npm-dist
path: packages/npm
if-no-files-found: error
retention-days: 7

publish:
name: Publish to npm
needs: build
if: needs.build.outputs.already_published != 'true'
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/npm

permissions:
contents: read
id-token: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"

- name: Install
run: npm ci || npm install --no-audit --no-fund

- name: Build
run: npm run build

- name: Publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
IS_PRE="${{ needs.build.outputs.is_prerelease }}"
if [ "${IS_PRE}" = "true" ]; then
npm publish --access public --tag next --provenance
else
npm publish --access public --provenance
fi

skipped:
name: Publish skipped (version already on npm)
needs: build
if: needs.build.outputs.already_published == 'true'
runs-on: ubuntu-latest
steps:
- name: Report
run: |
echo "::warning::@gradata/cli@${{ needs.build.outputs.version }} already exists on npm."
echo "::warning::Bump packages/npm/package.json and retag if you intended to publish a new version."
12 changes: 9 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ package.json
package-lock.json
# Exception: npm packages we intentionally ship
!gradata-install/package.json
!packages/npm/package.json
!packages/**/package.json

# Sales data (private, never in public repo)
Leads/
Expand Down Expand Up @@ -122,13 +124,16 @@ docs/north-star-research.md
# Internal dev tooling — not part of SDK
CLAUDE.md
FEATURES.md
Dockerfile
.dockerignore
.claude/
packages/
docs/GTM-Execution-Plan.md
docs/gradata-comparison-table.md

# npm package build artifacts (sources tracked, outputs ignored)
packages/npm/node_modules/
packages/npm/dist/
packages/*/node_modules/
packages/*/dist/

# Secrets
.env
.env.*
Expand Down Expand Up @@ -157,6 +162,7 @@ templates/
research/
!docs/research/
scripts/*
!scripts/publish-npm.sh
!cloud/scripts/
!scripts/migrate_legacy_scopes.py
docs/cloud/
Expand Down
Loading
Loading