Skip to content
Closed
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
84 changes: 84 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ on:
push:
branches: [main]

permissions:
contents: read

env:
DAYTONA_API_KEY: ${{ secrets.DAYTONA_API_KEY }}
DAYTONA_API_URL: ${{ vars.DAYTONA_API_URL }}
ZHIPU_API_KEY: ${{ secrets.ZHIPU_API_KEY }}

jobs:
Check:
name: Check
Expand All @@ -27,3 +35,79 @@ jobs:

- name: TypeScript typecheck
run: bun run typecheck

- name: Unit tests
run: bun test

- name: CLI smoke checks
run: |
bun run analyze -- --help
bun run start -- --help
bun run setup -- --help

BuildPackage:
name: Build Package Artifact
runs-on: blacksmith-4vcpu-ubuntu-2404
needs: Check
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.8

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Build package
run: bun run build

- name: Pack tarball
run: |
mkdir -p artifacts
npm pack --pack-destination artifacts
ls -la artifacts

- name: Upload package artifact
uses: actions/upload-artifact@v4
with:
name: npm-package
path: artifacts/*.tgz
if-no-files-found: error

PackageE2E:
name: Package Install E2E
runs-on: blacksmith-4vcpu-ubuntu-2404
needs: BuildPackage
steps:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Download package artifact
uses: actions/download-artifact@v4
with:
name: npm-package
path: artifacts

- name: Install package into clean project
run: |
mkdir e2e-install
cd e2e-install
npm init -y
npm install ../artifacts/*.tgz

- name: Run installed CLI binaries
run: |
cd e2e-install
./node_modules/.bin/opencode-sandboxed-research-analyze --help
./node_modules/.bin/opencode-sandboxed-research-start --help
./node_modules/.bin/opencode-sandboxed-research-setup --help
70 changes: 70 additions & 0 deletions .github/workflows/daytona-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Daytona E2E

on:
workflow_dispatch:
inputs:
repo_url:
description: "Repository URL to analyze"
required: false
default: "https://github.com/octocat/Hello-World"
model:
description: "Model to use"
required: false
default: "zai-coding-plan/glm-4.7-flash"
analyze_timeout_sec:
description: "Analyze timeout seconds"
required: false
default: "600"
install_timeout_sec:
description: "Install timeout seconds"
required: false
default: "300"

permissions:
contents: read

env:
DAYTONA_API_KEY: ${{ secrets.DAYTONA_API_KEY }}
DAYTONA_API_URL: ${{ vars.DAYTONA_API_URL }}
ZHIPU_API_KEY: ${{ secrets.ZHIPU_API_KEY }}

jobs:
E2E:
name: Run Daytona Analyze E2E
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.8

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Validate required environment
run: |
if [ -z "${DAYTONA_API_KEY:-}" ]; then
echo "DAYTONA_API_KEY is required" >&2
exit 1
fi

- name: Run analyze e2e
run: |
mkdir -p .memory/daytona-e2e
bun run analyze -- \
--out-dir .memory/daytona-e2e/findings \
--model "${{ inputs.model }}" \
--install-timeout-sec "${{ inputs.install_timeout_sec }}" \
--analyze-timeout-sec "${{ inputs.analyze_timeout_sec }}" \
"${{ inputs.repo_url }}"

- name: Upload findings artifact
uses: actions/upload-artifact@v4
with:
name: daytona-e2e-findings
path: .memory/daytona-e2e/findings
if-no-files-found: error
231 changes: 231 additions & 0 deletions .github/workflows/publish-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
name: Publish Package

on:
push:
branches: [main]

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

permissions:
contents: write
pull-requests: write
packages: write

jobs:
require-pr-merge:
name: Require PR Merge
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: read
pull-requests: read
steps:
- name: Ensure push commit came from merged PR
uses: actions/github-script@v7
with:
script: |
const query = `
query($owner: String!, $repo: String!, $oid: GitObjectID!) {
repository(owner: $owner, name: $repo) {
object(oid: $oid) {
... on Commit {
oid
associatedPullRequests(first: 10) {
nodes {
number
state
mergedAt
url
}
}
}
}
}
}
`;

const maxAttempts = 6;
const retryDelayMs = 5000;

const findMergedPr = async () => {
const data = await github.graphql(query, {
owner: context.repo.owner,
repo: context.repo.repo,
oid: context.sha,
});

const commit = data.repository?.object;
if (!commit) {
throw new Error(`Could not load commit ${context.sha}`);
}

const pullRequests = commit.associatedPullRequests?.nodes ?? [];
return pullRequests.find(
(pr) =>
pr.state === "MERGED" &&
typeof pr.mergedAt === "string" &&
pr.mergedAt.length > 0,
);
};

let mergedPr;
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
mergedPr = await findMergedPr();
if (mergedPr) {
break;
}

if (attempt < maxAttempts) {
core.info(
`No merged PR associated with ${context.sha} yet (attempt ${attempt}/${maxAttempts}); retrying in ${retryDelayMs / 1000}s.`,
);
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
}
}

if (!mergedPr) {
core.setFailed(
`Direct push detected on main at ${context.sha}. Publish flow requires merged PR commits only.`,
);
return;
}

core.info(
`Publish gate passed via merged PR #${mergedPr.number} (${mergedPr.url})`,
);

publish-and-bump:
name: Publish Next + Open Bump PR
runs-on: blacksmith-4vcpu-ubuntu-2404
needs: require-pr-merge
permissions:
contents: write
pull-requests: write
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.8

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Validate package
run: |
bun run check
bun run typecheck
bun test
bun run build

- name: Resolve package metadata
id: meta
run: |
node <<'NODE'
const fs = require("node:fs");
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
const match = /^0\.0\.(\d+)$/.exec(pkg.version ?? "");

if (!pkg.name) {
console.error("Missing package name in package.json");
process.exit(1);
}

if (!match) {
console.error(
`package.json version must match 0.0.x for this release flow. Received: ${pkg.version}`,
);
process.exit(1);
}

const nextVersion = `0.0.${Number(match[1]) + 1}`;
fs.appendFileSync(process.env.GITHUB_OUTPUT, `name=${pkg.name}\n`);
fs.appendFileSync(process.env.GITHUB_OUTPUT, `version=${pkg.version}\n`);
fs.appendFileSync(process.env.GITHUB_OUTPUT, `next_version=${nextVersion}\n`);
NODE

- name: Configure npm for GitHub Packages
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npm config set @shpitdev:registry https://npm.pkg.github.com
npm config set //npm.pkg.github.com/:_authToken "$NODE_AUTH_TOKEN"
npm config set always-auth true

- name: Publish package with next tag
id: publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PACKAGE_REF="${{ steps.meta.outputs.name }}@${{ steps.meta.outputs.version }}"

if npm view "$PACKAGE_REF" version --registry https://npm.pkg.github.com >/dev/null 2>&1; then
echo "Version $PACKAGE_REF already exists in GitHub Packages; skipping publish."
echo "published=false" >> "$GITHUB_OUTPUT"
exit 0
fi

npm publish --registry https://npm.pkg.github.com --tag next
echo "published=true" >> "$GITHUB_OUTPUT"

- name: Verify registry install
if: steps.publish.outputs.published == 'true'
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PACKAGE_REF="${{ steps.meta.outputs.name }}@${{ steps.meta.outputs.version }}"

mkdir -p e2e-install
cd e2e-install
npm init -y

for attempt in 1 2 3 4 5 6; do
if npm install "$PACKAGE_REF"; then
break
fi

if [ "$attempt" -eq 6 ]; then
echo "Failed to install $PACKAGE_REF after retries" >&2
exit 1
fi

sleep 10
done

./node_modules/.bin/opencode-sandboxed-research-analyze --help
./node_modules/.bin/opencode-sandboxed-research-start --help
./node_modules/.bin/opencode-sandboxed-research-setup --help

- name: Prepare next patch bump
run: |
node <<'NODE'
const fs = require("node:fs");
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
pkg.version = "${{ steps.meta.outputs.next_version }}";
fs.writeFileSync("package.json", `${JSON.stringify(pkg, null, 2)}\n`);
NODE

- name: Open bump PR
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
branch: ci/version-bump-${{ steps.meta.outputs.next_version }}
delete-branch: true
commit-message: "chore: bump package version to ${{ steps.meta.outputs.next_version }}"
title: "chore: bump package version to ${{ steps.meta.outputs.next_version }}"
body: |
Automated post-publish bump.

- Published `${{ steps.meta.outputs.name }}@${{ steps.meta.outputs.version }}` with npm tag `next`
- Next patch version prepared: `${{ steps.meta.outputs.next_version }}`
add-paths: |
package.json
Loading