openhands-automation 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openhands_automation-1.0.0/.dockerignore +32 -0
- openhands_automation-1.0.0/.github/workflows/ci.yml +56 -0
- openhands_automation-1.0.0/.github/workflows/ghcr-build.yml +102 -0
- openhands_automation-1.0.0/.github/workflows/pr-artifacts.yml +142 -0
- openhands_automation-1.0.0/.github/workflows/prepare-release.yml +135 -0
- openhands_automation-1.0.0/.github/workflows/promote-to-development.yml +90 -0
- openhands_automation-1.0.0/.github/workflows/pypi-release.yml +40 -0
- openhands_automation-1.0.0/.github/workflows/qa-changes-by-openhands.yml +41 -0
- openhands_automation-1.0.0/.github/workflows/tag-image.yml +70 -0
- openhands_automation-1.0.0/.github/workflows/tests.yml +49 -0
- openhands_automation-1.0.0/.gitignore +193 -0
- openhands_automation-1.0.0/.pre-commit-config.yaml +45 -0
- openhands_automation-1.0.0/.python-version +1 -0
- openhands_automation-1.0.0/AGENTS.md +304 -0
- openhands_automation-1.0.0/LICENSE +21 -0
- openhands_automation-1.0.0/Makefile +96 -0
- openhands_automation-1.0.0/PKG-INFO +131 -0
- openhands_automation-1.0.0/README.md +97 -0
- openhands_automation-1.0.0/alembic.ini +37 -0
- openhands_automation-1.0.0/containers/Dockerfile +45 -0
- openhands_automation-1.0.0/docs/kv-store-client-guide.md +451 -0
- openhands_automation-1.0.0/docs/kv-store-design.md +910 -0
- openhands_automation-1.0.0/docs/kv-store-test-plan.md +147 -0
- openhands_automation-1.0.0/frontend/.env.example +3 -0
- openhands_automation-1.0.0/frontend/.eslintrc +73 -0
- openhands_automation-1.0.0/frontend/.gitignore +10 -0
- openhands_automation-1.0.0/frontend/.husky/pre-commit +2 -0
- openhands_automation-1.0.0/frontend/.prettierrc.json +3 -0
- openhands_automation-1.0.0/frontend/README.md +234 -0
- openhands_automation-1.0.0/frontend/__mocks__/zustand.ts +60 -0
- openhands_automation-1.0.0/frontend/commitlint.config.cjs +3 -0
- openhands_automation-1.0.0/frontend/package-lock.json +12444 -0
- openhands_automation-1.0.0/frontend/package.json +109 -0
- openhands_automation-1.0.0/frontend/playwright.config.ts +25 -0
- openhands_automation-1.0.0/frontend/public/mockServiceWorker.js +349 -0
- openhands_automation-1.0.0/frontend/react-router.config.ts +28 -0
- openhands_automation-1.0.0/frontend/scripts/check-translation-completeness.cjs +102 -0
- openhands_automation-1.0.0/frontend/scripts/dev-proxy.mjs +101 -0
- openhands_automation-1.0.0/frontend/scripts/make-i18n-translations.cjs +51 -0
- openhands_automation-1.0.0/frontend/src/__tests__/api/automation-service.test.ts +180 -0
- openhands_automation-1.0.0/frontend/src/__tests__/api/openhands-service.test.ts +61 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/automation-card.test.tsx +136 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/automation-group.test.tsx +53 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/create-instructions.test.tsx +123 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/delete-confirmation-modal.test.tsx +71 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/active-status-badge.test.tsx +15 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/activity-log-item.test.tsx +240 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/activity-log-section.test.tsx +98 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/activity-section.test.tsx +79 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/back-link.test.tsx +29 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/branch-badge.test.tsx +15 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/config-field.test.tsx +29 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/configuration-section.test.tsx +74 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/detail-header.test.tsx +119 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/not-found-state.test.tsx +24 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/plugin-chip.test.tsx +15 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/plugins-section.test.tsx +21 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/prompt-section.test.tsx +21 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/run-status-badge.test.tsx +35 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/detail/section-card.test.tsx +17 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/empty-state.test.tsx +66 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/error-state.test.tsx +23 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/kebab-menu.test.tsx +63 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/metadata-chip.test.tsx +17 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/permission-gating.test.tsx +141 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/search-input.test.tsx +28 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/automations/toggle-switch.test.tsx +38 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/reauth-modal.test.tsx +12 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/shared/modals/modal-backdrop.test.tsx +76 -0
- openhands_automation-1.0.0/frontend/src/__tests__/components/shared/modals/modal-body.test.tsx +61 -0
- openhands_automation-1.0.0/frontend/src/__tests__/hooks/use-auto-login.test.ts +102 -0
- openhands_automation-1.0.0/frontend/src/__tests__/hooks/use-cross-tab-state.test.ts +54 -0
- openhands_automation-1.0.0/frontend/src/__tests__/hooks/use-escape-key.test.ts +53 -0
- openhands_automation-1.0.0/frontend/src/__tests__/hooks/use-has-permission.test.ts +83 -0
- openhands_automation-1.0.0/frontend/src/__tests__/hooks/use-is-authed.test.ts +75 -0
- openhands_automation-1.0.0/frontend/src/__tests__/hooks/use-language-sync.test.ts +142 -0
- openhands_automation-1.0.0/frontend/src/__tests__/hooks/use-me.test.ts +61 -0
- openhands_automation-1.0.0/frontend/src/__tests__/hooks/use-org-sync.test.ts +129 -0
- openhands_automation-1.0.0/frontend/src/__tests__/hooks/use-theme-sync.test.ts +114 -0
- openhands_automation-1.0.0/frontend/src/__tests__/routes/automation-detail.test.tsx +277 -0
- openhands_automation-1.0.0/frontend/src/__tests__/routes/automations-list.test.tsx +242 -0
- openhands_automation-1.0.0/frontend/src/__tests__/routes/root-layout.test.tsx +177 -0
- openhands_automation-1.0.0/frontend/src/__tests__/stores/user-store.test.ts +42 -0
- openhands_automation-1.0.0/frontend/src/__tests__/utils/generate-auth-url.test.ts +88 -0
- openhands_automation-1.0.0/frontend/src/__tests__/utils/local-storage.test.ts +60 -0
- openhands_automation-1.0.0/frontend/src/api/automation-service.ts +83 -0
- openhands_automation-1.0.0/frontend/src/api/axios-clients.ts +21 -0
- openhands_automation-1.0.0/frontend/src/api/openhands-service.ts +16 -0
- openhands_automation-1.0.0/frontend/src/assets/branding/openhands-logo.svg +9 -0
- openhands_automation-1.0.0/frontend/src/components/.gitkeep +0 -0
- openhands_automation-1.0.0/frontend/src/components/automations/automation-card-skeleton.tsx +19 -0
- openhands_automation-1.0.0/frontend/src/components/automations/automation-card.tsx +119 -0
- openhands_automation-1.0.0/frontend/src/components/automations/automation-group.tsx +40 -0
- openhands_automation-1.0.0/frontend/src/components/automations/create-instructions.tsx +119 -0
- openhands_automation-1.0.0/frontend/src/components/automations/delete-confirmation-modal.tsx +70 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/active-status-badge.tsx +24 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/activity-log-item.tsx +96 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/activity-log-section.tsx +82 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/activity-section.tsx +77 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/back-link.tsx +18 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/branch-badge.tsx +11 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/config-field.tsx +17 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/configuration-section.tsx +84 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/detail-header.tsx +84 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/detail-skeleton.tsx +28 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/not-found-state.tsx +23 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/plugin-chip.tsx +11 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/plugins-section.tsx +26 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/prompt-section.tsx +25 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/run-status-badge.tsx +62 -0
- openhands_automation-1.0.0/frontend/src/components/automations/detail/section-card.tsx +17 -0
- openhands_automation-1.0.0/frontend/src/components/automations/empty-state.tsx +22 -0
- openhands_automation-1.0.0/frontend/src/components/automations/error-state.tsx +27 -0
- openhands_automation-1.0.0/frontend/src/components/automations/kebab-menu.tsx +69 -0
- openhands_automation-1.0.0/frontend/src/components/automations/metadata-chip.tsx +13 -0
- openhands_automation-1.0.0/frontend/src/components/automations/search-input.tsx +25 -0
- openhands_automation-1.0.0/frontend/src/components/automations/status-badge.tsx +11 -0
- openhands_automation-1.0.0/frontend/src/components/automations/toggle-switch.tsx +33 -0
- openhands_automation-1.0.0/frontend/src/components/error-boundary.tsx +48 -0
- openhands_automation-1.0.0/frontend/src/components/reauth-modal.tsx +22 -0
- openhands_automation-1.0.0/frontend/src/components/shared/modals/modal-backdrop.tsx +35 -0
- openhands_automation-1.0.0/frontend/src/components/shared/modals/modal-body.tsx +32 -0
- openhands_automation-1.0.0/frontend/src/constants/.gitkeep +0 -0
- openhands_automation-1.0.0/frontend/src/entry.client.tsx +37 -0
- openhands_automation-1.0.0/frontend/src/hooks/.gitkeep +0 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-auth-url.ts +8 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-auto-login.ts +59 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-automation-detail.ts +23 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-automations.ts +35 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-cross-tab-state.ts +48 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-escape-key.ts +26 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-has-permission.ts +9 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-is-authed.ts +25 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-language-sync.ts +54 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-me.ts +18 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-org-sync.ts +40 -0
- openhands_automation-1.0.0/frontend/src/hooks/use-theme-sync.ts +39 -0
- openhands_automation-1.0.0/frontend/src/i18n/index.ts +38 -0
- openhands_automation-1.0.0/frontend/src/i18n/translation.json +1056 -0
- openhands_automation-1.0.0/frontend/src/icons/.gitkeep +0 -0
- openhands_automation-1.0.0/frontend/src/icons/activity.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/bell.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/calendar.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/check-circle.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/chevron-down.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/chevron-left.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/clock.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/cog.svg +4 -0
- openhands_automation-1.0.0/frontend/src/icons/database.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/download.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/exclamation-circle.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/folder.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/git-branch.svg +6 -0
- openhands_automation-1.0.0/frontend/src/icons/kebab-vertical.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/power.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/puzzle.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/search.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/sparkle.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/svg.d.ts +6 -0
- openhands_automation-1.0.0/frontend/src/icons/target.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/terminal.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/trash.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/x-circle.svg +3 -0
- openhands_automation-1.0.0/frontend/src/icons/x-mark.svg +3 -0
- openhands_automation-1.0.0/frontend/src/index.css +40 -0
- openhands_automation-1.0.0/frontend/src/mocks/auth-handlers.ts +41 -0
- openhands_automation-1.0.0/frontend/src/mocks/automation-handlers.ts +123 -0
- openhands_automation-1.0.0/frontend/src/mocks/automation-runs.mock.ts +61 -0
- openhands_automation-1.0.0/frontend/src/mocks/automations.mock.ts +127 -0
- openhands_automation-1.0.0/frontend/src/mocks/browser.ts +4 -0
- openhands_automation-1.0.0/frontend/src/mocks/handlers.ts +4 -0
- openhands_automation-1.0.0/frontend/src/mocks/node.ts +4 -0
- openhands_automation-1.0.0/frontend/src/query-client-config.ts +62 -0
- openhands_automation-1.0.0/frontend/src/root.tsx +35 -0
- openhands_automation-1.0.0/frontend/src/routes/automation-detail.tsx +98 -0
- openhands_automation-1.0.0/frontend/src/routes/automations-list.tsx +144 -0
- openhands_automation-1.0.0/frontend/src/routes/root-layout.tsx +119 -0
- openhands_automation-1.0.0/frontend/src/routes.ts +13 -0
- openhands_automation-1.0.0/frontend/src/stores/.gitkeep +0 -0
- openhands_automation-1.0.0/frontend/src/stores/user-store.ts +22 -0
- openhands_automation-1.0.0/frontend/src/tailwind.css +52 -0
- openhands_automation-1.0.0/frontend/src/types/.gitkeep +0 -0
- openhands_automation-1.0.0/frontend/src/types/automation.ts +52 -0
- openhands_automation-1.0.0/frontend/src/types/user.ts +9 -0
- openhands_automation-1.0.0/frontend/src/utils/custom-toast-handlers.tsx +42 -0
- openhands_automation-1.0.0/frontend/src/utils/generate-auth-url.ts +43 -0
- openhands_automation-1.0.0/frontend/src/utils/local-storage.ts +36 -0
- openhands_automation-1.0.0/frontend/src/utils/permissions.ts +8 -0
- openhands_automation-1.0.0/frontend/src/utils/toast-duration.ts +27 -0
- openhands_automation-1.0.0/frontend/src/utils/utils.ts +6 -0
- openhands_automation-1.0.0/frontend/tailwind.config.js +65 -0
- openhands_automation-1.0.0/frontend/tsconfig.json +30 -0
- openhands_automation-1.0.0/frontend/vite.config.ts +83 -0
- openhands_automation-1.0.0/frontend/vitest.setup.ts +39 -0
- openhands_automation-1.0.0/migrations/env.py +160 -0
- openhands_automation-1.0.0/migrations/script.py.mako +25 -0
- openhands_automation-1.0.0/migrations/versions/001_initial_schema.py +129 -0
- openhands_automation-1.0.0/migrations/versions/002_tarball_uploads.py +64 -0
- openhands_automation-1.0.0/migrations/versions/003_event_triggers.py +92 -0
- openhands_automation-1.0.0/migrations/versions/004_add_prompt_column.py +29 -0
- openhands_automation-1.0.0/migrations/versions/005_add_bash_command_id.py +37 -0
- openhands_automation-1.0.0/migrations/versions/006_add_model.py +25 -0
- openhands_automation-1.0.0/migrations/versions/007_add_automation_run_composite_indexes.py +44 -0
- openhands_automation-1.0.0/migrations/versions/008_add_kv_store.py +109 -0
- openhands_automation-1.0.0/migrations/versions/009_add_sandbox_cleanup_policy.py +47 -0
- openhands_automation-1.0.0/openhands/automation/__init__.py +3 -0
- openhands_automation-1.0.0/openhands/automation/app.py +332 -0
- openhands_automation-1.0.0/openhands/automation/auth.py +444 -0
- openhands_automation-1.0.0/openhands/automation/backends/__init__.py +68 -0
- openhands_automation-1.0.0/openhands/automation/backends/base.py +145 -0
- openhands_automation-1.0.0/openhands/automation/backends/cloud.py +332 -0
- openhands_automation-1.0.0/openhands/automation/backends/local.py +206 -0
- openhands_automation-1.0.0/openhands/automation/config.py +671 -0
- openhands_automation-1.0.0/openhands/automation/constants.py +86 -0
- openhands_automation-1.0.0/openhands/automation/db.py +249 -0
- openhands_automation-1.0.0/openhands/automation/dispatcher.py +496 -0
- openhands_automation-1.0.0/openhands/automation/event_router.py +192 -0
- openhands_automation-1.0.0/openhands/automation/event_schemas/__init__.py +132 -0
- openhands_automation-1.0.0/openhands/automation/event_schemas/bitbucket_data_center.py +38 -0
- openhands_automation-1.0.0/openhands/automation/event_schemas/custom.py +108 -0
- openhands_automation-1.0.0/openhands/automation/event_schemas/detection.py +136 -0
- openhands_automation-1.0.0/openhands/automation/event_schemas/github.py +483 -0
- openhands_automation-1.0.0/openhands/automation/event_schemas/jira_dc.py +35 -0
- openhands_automation-1.0.0/openhands/automation/exceptions.py +40 -0
- openhands_automation-1.0.0/openhands/automation/execution.py +591 -0
- openhands_automation-1.0.0/openhands/automation/filter_eval.py +192 -0
- openhands_automation-1.0.0/openhands/automation/kv_helpers.py +399 -0
- openhands_automation-1.0.0/openhands/automation/kv_metrics.py +114 -0
- openhands_automation-1.0.0/openhands/automation/kv_router.py +1139 -0
- openhands_automation-1.0.0/openhands/automation/kv_schemas.py +249 -0
- openhands_automation-1.0.0/openhands/automation/logger.py +115 -0
- openhands_automation-1.0.0/openhands/automation/middleware.py +69 -0
- openhands_automation-1.0.0/openhands/automation/models.py +392 -0
- openhands_automation-1.0.0/openhands/automation/preset_router.py +851 -0
- openhands_automation-1.0.0/openhands/automation/presets/__init__.py +9 -0
- openhands_automation-1.0.0/openhands/automation/presets/plugin/sdk_main.py +430 -0
- openhands_automation-1.0.0/openhands/automation/presets/plugin/setup.sh +48 -0
- openhands_automation-1.0.0/openhands/automation/presets/prompt/sdk_main.py +379 -0
- openhands_automation-1.0.0/openhands/automation/presets/prompt/setup.sh +48 -0
- openhands_automation-1.0.0/openhands/automation/router.py +548 -0
- openhands_automation-1.0.0/openhands/automation/scheduler.py +205 -0
- openhands_automation-1.0.0/openhands/automation/schemas.py +650 -0
- openhands_automation-1.0.0/openhands/automation/storage/__init__.py +18 -0
- openhands_automation-1.0.0/openhands/automation/storage/factory.py +36 -0
- openhands_automation-1.0.0/openhands/automation/storage/file_store.py +64 -0
- openhands_automation-1.0.0/openhands/automation/storage/google_cloud.py +195 -0
- openhands_automation-1.0.0/openhands/automation/storage/local.py +125 -0
- openhands_automation-1.0.0/openhands/automation/storage/s3.py +340 -0
- openhands_automation-1.0.0/openhands/automation/trigger_matcher.py +89 -0
- openhands_automation-1.0.0/openhands/automation/uploads.py +323 -0
- openhands_automation-1.0.0/openhands/automation/utils/__init__.py +26 -0
- openhands_automation-1.0.0/openhands/automation/utils/agent_server.py +184 -0
- openhands_automation-1.0.0/openhands/automation/utils/api_key.py +98 -0
- openhands_automation-1.0.0/openhands/automation/utils/cron.py +143 -0
- openhands_automation-1.0.0/openhands/automation/utils/kv.py +218 -0
- openhands_automation-1.0.0/openhands/automation/utils/log_context.py +31 -0
- openhands_automation-1.0.0/openhands/automation/utils/model_profiles.py +39 -0
- openhands_automation-1.0.0/openhands/automation/utils/run.py +268 -0
- openhands_automation-1.0.0/openhands/automation/utils/sandbox.py +211 -0
- openhands_automation-1.0.0/openhands/automation/utils/tarball_validation.py +170 -0
- openhands_automation-1.0.0/openhands/automation/utils/time.py +41 -0
- openhands_automation-1.0.0/openhands/automation/utils/webhook.py +237 -0
- openhands_automation-1.0.0/openhands/automation/watchdog.py +328 -0
- openhands_automation-1.0.0/openhands/automation/webhook_router.py +275 -0
- openhands_automation-1.0.0/pyproject.toml +133 -0
- openhands_automation-1.0.0/scripts/test_automation.py +190 -0
- openhands_automation-1.0.0/scripts/test_kv_e2e.py +955 -0
- openhands_automation-1.0.0/scripts/test_tarball/main.py +131 -0
- openhands_automation-1.0.0/scripts/test_tarball/setup.sh +40 -0
- openhands_automation-1.0.0/tests/__init__.py +0 -0
- openhands_automation-1.0.0/tests/conftest.py +205 -0
- openhands_automation-1.0.0/tests/test_ab_testing_integration.py +526 -0
- openhands_automation-1.0.0/tests/test_auth.py +1087 -0
- openhands_automation-1.0.0/tests/test_backends.py +554 -0
- openhands_automation-1.0.0/tests/test_cancel_run.py +131 -0
- openhands_automation-1.0.0/tests/test_config.py +434 -0
- openhands_automation-1.0.0/tests/test_cors.py +193 -0
- openhands_automation-1.0.0/tests/test_db.py +332 -0
- openhands_automation-1.0.0/tests/test_disable_automation.py +525 -0
- openhands_automation-1.0.0/tests/test_dispatcher.py +813 -0
- openhands_automation-1.0.0/tests/test_event_router.py +538 -0
- openhands_automation-1.0.0/tests/test_event_schemas.py +1006 -0
- openhands_automation-1.0.0/tests/test_execution.py +485 -0
- openhands_automation-1.0.0/tests/test_filter_eval.py +282 -0
- openhands_automation-1.0.0/tests/test_frontend.py +188 -0
- openhands_automation-1.0.0/tests/test_health.py +77 -0
- openhands_automation-1.0.0/tests/test_kv_batch.py +433 -0
- openhands_automation-1.0.0/tests/test_kv_concurrency.py +156 -0
- openhands_automation-1.0.0/tests/test_kv_helpers.py +629 -0
- openhands_automation-1.0.0/tests/test_kv_router.py +832 -0
- openhands_automation-1.0.0/tests/test_local_mode.py +384 -0
- openhands_automation-1.0.0/tests/test_openapi.py +30 -0
- openhands_automation-1.0.0/tests/test_preset_router.py +1672 -0
- openhands_automation-1.0.0/tests/test_router.py +2169 -0
- openhands_automation-1.0.0/tests/test_scheduler.py +953 -0
- openhands_automation-1.0.0/tests/test_schemas.py +137 -0
- openhands_automation-1.0.0/tests/test_storage.py +240 -0
- openhands_automation-1.0.0/tests/test_storage_integration.py +252 -0
- openhands_automation-1.0.0/tests/test_storage_local.py +362 -0
- openhands_automation-1.0.0/tests/test_storage_s3.py +399 -0
- openhands_automation-1.0.0/tests/test_storage_s3_integration.py +324 -0
- openhands_automation-1.0.0/tests/test_tarball_validation.py +333 -0
- openhands_automation-1.0.0/tests/test_test_tarball_setup.py +21 -0
- openhands_automation-1.0.0/tests/test_uploads.py +192 -0
- openhands_automation-1.0.0/tests/test_uploads_integration.py +227 -0
- openhands_automation-1.0.0/tests/test_watchdog.py +378 -0
- openhands_automation-1.0.0/tests/test_webhook_router.py +304 -0
- openhands_automation-1.0.0/tests/test_webhook_utils.py +322 -0
- openhands_automation-1.0.0/uv.lock +4181 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Version control
|
|
2
|
+
.git
|
|
3
|
+
.gitignore
|
|
4
|
+
|
|
5
|
+
# CI/CD
|
|
6
|
+
.github
|
|
7
|
+
|
|
8
|
+
# Python
|
|
9
|
+
.venv
|
|
10
|
+
__pycache__
|
|
11
|
+
*.pyc
|
|
12
|
+
.pytest_cache
|
|
13
|
+
.ruff_cache
|
|
14
|
+
.mypy_cache
|
|
15
|
+
|
|
16
|
+
# Frontend (built inside Docker via multi-stage)
|
|
17
|
+
frontend/node_modules
|
|
18
|
+
frontend/build
|
|
19
|
+
frontend/coverage
|
|
20
|
+
frontend/test-results
|
|
21
|
+
frontend/playwright-report
|
|
22
|
+
frontend/.react-router
|
|
23
|
+
|
|
24
|
+
# IDE / editor
|
|
25
|
+
.vscode
|
|
26
|
+
.idea
|
|
27
|
+
*.swp
|
|
28
|
+
|
|
29
|
+
# Misc
|
|
30
|
+
.pr
|
|
31
|
+
.stakpak
|
|
32
|
+
.pre-commit-config.yaml
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
# .github/workflows/precommit.yml
|
|
3
|
+
name: ci
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: ['**']
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
backend:
|
|
13
|
+
runs-on: ubuntu-24.04
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout code
|
|
17
|
+
uses: actions/checkout@v5
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v6
|
|
21
|
+
with:
|
|
22
|
+
python-version: '3.12'
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v7
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: uv sync --frozen --group dev
|
|
29
|
+
|
|
30
|
+
- name: Run pre-commit (all files)
|
|
31
|
+
run: uv run pre-commit run --all-files --show-diff-on-failure
|
|
32
|
+
|
|
33
|
+
frontend:
|
|
34
|
+
runs-on: ubuntu-24.04
|
|
35
|
+
defaults:
|
|
36
|
+
run:
|
|
37
|
+
working-directory: frontend
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v5
|
|
40
|
+
|
|
41
|
+
- name: Setup Node
|
|
42
|
+
uses: actions/setup-node@v3
|
|
43
|
+
with:
|
|
44
|
+
node-version: 24
|
|
45
|
+
|
|
46
|
+
- name: NPM dependencies
|
|
47
|
+
run: npm ci
|
|
48
|
+
|
|
49
|
+
- name: Lint
|
|
50
|
+
run: npm run lint
|
|
51
|
+
|
|
52
|
+
- name: Test
|
|
53
|
+
run: npm run test
|
|
54
|
+
|
|
55
|
+
- name: Build
|
|
56
|
+
run: npm run build
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Workflow that builds and pushes the automation docker image to ghcr.io
|
|
3
|
+
name: Docker
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches:
|
|
8
|
+
- main
|
|
9
|
+
tags:
|
|
10
|
+
- '*'
|
|
11
|
+
pull_request:
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
inputs:
|
|
14
|
+
reason:
|
|
15
|
+
description: Reason for manual trigger
|
|
16
|
+
required: true
|
|
17
|
+
default: ''
|
|
18
|
+
|
|
19
|
+
# If triggered by a PR, it will be in the same group. However, each commit on main will be in its own unique group
|
|
20
|
+
concurrency:
|
|
21
|
+
group: ${{ github.workflow }}-${{ (github.head_ref && github.ref) || github.run_id }}
|
|
22
|
+
cancel-in-progress: true
|
|
23
|
+
|
|
24
|
+
env:
|
|
25
|
+
REGISTRY: ghcr.io
|
|
26
|
+
IMAGE_NAME: openhands/automation
|
|
27
|
+
RELEVANT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
28
|
+
|
|
29
|
+
jobs:
|
|
30
|
+
ghcr_build:
|
|
31
|
+
name: Build and Push Automation Image
|
|
32
|
+
runs-on: ubuntu-24.04
|
|
33
|
+
permissions:
|
|
34
|
+
contents: read
|
|
35
|
+
packages: write
|
|
36
|
+
steps:
|
|
37
|
+
- name: Checkout
|
|
38
|
+
uses: actions/checkout@v4
|
|
39
|
+
with:
|
|
40
|
+
ref: ${{ github.event.pull_request.head.sha }}
|
|
41
|
+
|
|
42
|
+
- name: Set up Docker Buildx
|
|
43
|
+
uses: docker/setup-buildx-action@v3
|
|
44
|
+
with:
|
|
45
|
+
driver-opts: network=host
|
|
46
|
+
|
|
47
|
+
- name: Login to GHCR
|
|
48
|
+
uses: docker/login-action@v3
|
|
49
|
+
with:
|
|
50
|
+
registry: ${{ env.REGISTRY }}
|
|
51
|
+
username: ${{ github.repository_owner }}
|
|
52
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
53
|
+
|
|
54
|
+
- name: Get short SHA
|
|
55
|
+
id: short_sha
|
|
56
|
+
run: echo "SHORT_SHA=$(echo ${{ env.RELEVANT_SHA }} | cut -c1-7)" >> $GITHUB_OUTPUT
|
|
57
|
+
|
|
58
|
+
- name: Extract metadata (tags, labels) for Docker
|
|
59
|
+
id: meta
|
|
60
|
+
uses: docker/metadata-action@v5
|
|
61
|
+
with:
|
|
62
|
+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
63
|
+
tags: |
|
|
64
|
+
type=ref,event=branch
|
|
65
|
+
type=ref,event=pr
|
|
66
|
+
type=sha
|
|
67
|
+
type=sha,format=long
|
|
68
|
+
type=semver,pattern={{version}}
|
|
69
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
70
|
+
type=semver,pattern={{major}}
|
|
71
|
+
flavor: |
|
|
72
|
+
latest=auto
|
|
73
|
+
prefix=
|
|
74
|
+
suffix=
|
|
75
|
+
env:
|
|
76
|
+
DOCKER_METADATA_PR_HEAD_SHA: true
|
|
77
|
+
|
|
78
|
+
- name: Build and push Docker image
|
|
79
|
+
if: '!github.event.pull_request.head.repo.fork'
|
|
80
|
+
uses: docker/build-push-action@v5
|
|
81
|
+
with:
|
|
82
|
+
context: .
|
|
83
|
+
file: containers/Dockerfile
|
|
84
|
+
push: true
|
|
85
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
86
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
87
|
+
platforms: linux/amd64
|
|
88
|
+
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
|
|
89
|
+
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
|
|
90
|
+
provenance: true
|
|
91
|
+
sbom: true
|
|
92
|
+
|
|
93
|
+
# Forked repos can't push to GHCR, so we just build to verify the image builds
|
|
94
|
+
- name: Build Docker image (fork)
|
|
95
|
+
if: github.event.pull_request.head.repo.fork
|
|
96
|
+
uses: docker/build-push-action@v5
|
|
97
|
+
with:
|
|
98
|
+
context: .
|
|
99
|
+
file: containers/Dockerfile
|
|
100
|
+
push: false
|
|
101
|
+
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.RELEVANT_SHA }}
|
|
102
|
+
platforms: linux/amd64
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: PR Artifacts
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
workflow_dispatch: # Manual trigger for testing
|
|
6
|
+
pull_request:
|
|
7
|
+
types: [opened, synchronize, reopened]
|
|
8
|
+
branches: [main]
|
|
9
|
+
pull_request_review:
|
|
10
|
+
types: [submitted]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
# Auto-remove .pr/ directory when a reviewer approves
|
|
14
|
+
cleanup-on-approval:
|
|
15
|
+
concurrency:
|
|
16
|
+
group: cleanup-pr-artifacts-${{ github.event.pull_request.number }}
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
if: github.event_name == 'pull_request_review' && github.event.review.state == 'approved'
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
permissions:
|
|
21
|
+
contents: write
|
|
22
|
+
pull-requests: write
|
|
23
|
+
steps:
|
|
24
|
+
- name: Check if fork PR
|
|
25
|
+
id: check-fork
|
|
26
|
+
env:
|
|
27
|
+
PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
|
|
28
|
+
PR_BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }}
|
|
29
|
+
run: |
|
|
30
|
+
if [ "$PR_HEAD_REPO" != "$PR_BASE_REPO" ]; then
|
|
31
|
+
echo "is_fork=true" >> $GITHUB_OUTPUT
|
|
32
|
+
echo "::notice::Fork PR detected - skipping auto-cleanup (manual removal required)"
|
|
33
|
+
else
|
|
34
|
+
echo "is_fork=false" >> $GITHUB_OUTPUT
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# Use PAT so the push triggers CI workflows that will complete and
|
|
38
|
+
# satisfy branch protection. We can't use [skip ci] because GitHub Apps
|
|
39
|
+
# can create stuck checks that block merging.
|
|
40
|
+
- uses: actions/checkout@v6
|
|
41
|
+
if: steps.check-fork.outputs.is_fork == 'false'
|
|
42
|
+
with:
|
|
43
|
+
ref: ${{ github.event.pull_request.head.ref }}
|
|
44
|
+
token: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC }}
|
|
45
|
+
|
|
46
|
+
- name: Remove .pr/ directory
|
|
47
|
+
id: remove
|
|
48
|
+
if: steps.check-fork.outputs.is_fork == 'false'
|
|
49
|
+
run: |
|
|
50
|
+
if [ -d ".pr" ]; then
|
|
51
|
+
git config user.name "allhands-bot"
|
|
52
|
+
git config user.email "allhands-bot@users.noreply.github.com"
|
|
53
|
+
git rm -rf .pr/
|
|
54
|
+
git commit -m "chore: Remove PR-only artifacts [automated]"
|
|
55
|
+
git push || {
|
|
56
|
+
echo "::error::Failed to push cleanup commit. Check branch protection rules."
|
|
57
|
+
exit 1
|
|
58
|
+
}
|
|
59
|
+
echo "removed=true" >> $GITHUB_OUTPUT
|
|
60
|
+
echo "::notice::Removed .pr/ directory"
|
|
61
|
+
else
|
|
62
|
+
echo "removed=false" >> $GITHUB_OUTPUT
|
|
63
|
+
echo "::notice::No .pr/ directory to remove"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
- name: Update PR comment after cleanup
|
|
67
|
+
if: steps.check-fork.outputs.is_fork == 'false' && steps.remove.outputs.removed == 'true'
|
|
68
|
+
uses: actions/github-script@v9
|
|
69
|
+
with:
|
|
70
|
+
script: |
|
|
71
|
+
const marker = '<!-- pr-artifacts-notice -->';
|
|
72
|
+
const body = `${marker}
|
|
73
|
+
✅ **PR Artifacts Cleaned Up**
|
|
74
|
+
|
|
75
|
+
The \`.pr/\` directory has been automatically removed.
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
const { data: comments } = await github.rest.issues.listComments({
|
|
79
|
+
owner: context.repo.owner,
|
|
80
|
+
repo: context.repo.repo,
|
|
81
|
+
issue_number: context.issue.number,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const existing = comments.find(c => c.body.includes(marker));
|
|
85
|
+
if (existing) {
|
|
86
|
+
await github.rest.issues.updateComment({
|
|
87
|
+
owner: context.repo.owner,
|
|
88
|
+
repo: context.repo.repo,
|
|
89
|
+
comment_id: existing.id,
|
|
90
|
+
body: body,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
# Warn if .pr/ directory exists (will be auto-removed on approval)
|
|
95
|
+
check-pr-artifacts:
|
|
96
|
+
if: github.event_name == 'pull_request'
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
permissions:
|
|
99
|
+
contents: read
|
|
100
|
+
pull-requests: write
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@v6
|
|
103
|
+
|
|
104
|
+
- name: Check for .pr/ directory
|
|
105
|
+
id: check
|
|
106
|
+
run: |
|
|
107
|
+
if [ -d ".pr" ]; then
|
|
108
|
+
echo "exists=true" >> $GITHUB_OUTPUT
|
|
109
|
+
echo "::warning::the .pr/ directory is a temporary directory, intended by this repository policy to be used to show live tests artifacts for review. It will be automatically removed when the PR is approved. For fork PRs, manual removal is required before merging."
|
|
110
|
+
else
|
|
111
|
+
echo "exists=false" >> $GITHUB_OUTPUT
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
- name: Post or update PR comment
|
|
115
|
+
if: steps.check.outputs.exists == 'true'
|
|
116
|
+
uses: actions/github-script@v9
|
|
117
|
+
with:
|
|
118
|
+
script: |
|
|
119
|
+
const marker = '<!-- pr-artifacts-notice -->';
|
|
120
|
+
const body = `${marker}
|
|
121
|
+
📁 **PR Artifacts Notice**
|
|
122
|
+
|
|
123
|
+
This PR contains a \`.pr/\` directory with PR-specific documents. This directory will be **automatically removed** when the PR is approved.
|
|
124
|
+
|
|
125
|
+
> For fork PRs: Manual removal is required before merging.
|
|
126
|
+
`;
|
|
127
|
+
|
|
128
|
+
const { data: comments } = await github.rest.issues.listComments({
|
|
129
|
+
owner: context.repo.owner,
|
|
130
|
+
repo: context.repo.repo,
|
|
131
|
+
issue_number: context.issue.number,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const existing = comments.find(c => c.body.includes(marker));
|
|
135
|
+
if (!existing) {
|
|
136
|
+
await github.rest.issues.createComment({
|
|
137
|
+
owner: context.repo.owner,
|
|
138
|
+
repo: context.repo.repo,
|
|
139
|
+
issue_number: context.issue.number,
|
|
140
|
+
body: body,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Workflow that prepares a release by bumping the version and opening a PR.
|
|
3
|
+
# Triggered manually via workflow_dispatch with a version input.
|
|
4
|
+
# After the PR is merged, create and push a tag to trigger the actual release.
|
|
5
|
+
name: Prepare Release
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
inputs:
|
|
10
|
+
version:
|
|
11
|
+
description: Version to release (e.g., 1.0.0, 1.0.0a3, 1.0.0b1)
|
|
12
|
+
required: true
|
|
13
|
+
type: string
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
prepare-release:
|
|
17
|
+
name: Prepare Release PR
|
|
18
|
+
runs-on: ubuntu-24.04
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write
|
|
21
|
+
pull-requests: write
|
|
22
|
+
steps:
|
|
23
|
+
- name: Validate version format
|
|
24
|
+
run: |
|
|
25
|
+
VERSION="${{ inputs.version }}"
|
|
26
|
+
# Basic PEP 440 validation (allows: X.Y.Z, X.Y.ZaN, X.Y.ZbN, X.Y.ZrcN)
|
|
27
|
+
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(a[0-9]+|b[0-9]+|rc[0-9]+)?$'; then
|
|
28
|
+
echo "::error::Invalid version format: $VERSION"
|
|
29
|
+
echo "Expected format: X.Y.Z, X.Y.ZaN (alpha), X.Y.ZbN (beta), or X.Y.ZrcN (release candidate)"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
- name: Checkout
|
|
34
|
+
uses: actions/checkout@v4
|
|
35
|
+
with:
|
|
36
|
+
token: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC }}
|
|
37
|
+
fetch-depth: 0
|
|
38
|
+
|
|
39
|
+
- name: Install uv
|
|
40
|
+
uses: astral-sh/setup-uv@v7
|
|
41
|
+
with:
|
|
42
|
+
version: latest
|
|
43
|
+
|
|
44
|
+
- name: Set up Python
|
|
45
|
+
run: uv python install 3.12
|
|
46
|
+
|
|
47
|
+
- name: Get current version
|
|
48
|
+
id: current
|
|
49
|
+
run: |
|
|
50
|
+
CURRENT=$(grep -oP '^version = "\K[^"]+' pyproject.toml)
|
|
51
|
+
echo "version=$CURRENT" >> $GITHUB_OUTPUT
|
|
52
|
+
echo "Current version: $CURRENT"
|
|
53
|
+
|
|
54
|
+
- name: Bump version
|
|
55
|
+
run: |
|
|
56
|
+
VERSION="${{ inputs.version }}"
|
|
57
|
+
CURRENT="${{ steps.current.outputs.version }}"
|
|
58
|
+
if [ "$CURRENT" = "$VERSION" ]; then
|
|
59
|
+
echo "::error::Version $VERSION is already set in pyproject.toml"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
|
|
63
|
+
if ! grep -q "^version = \"$VERSION\"" pyproject.toml; then
|
|
64
|
+
echo "::error::Failed to update version in pyproject.toml"
|
|
65
|
+
exit 1
|
|
66
|
+
fi
|
|
67
|
+
echo "Updated pyproject.toml to version $VERSION"
|
|
68
|
+
grep '^version = ' pyproject.toml
|
|
69
|
+
|
|
70
|
+
- name: Update lockfile
|
|
71
|
+
run: |
|
|
72
|
+
uv lock
|
|
73
|
+
if ! git diff --quiet uv.lock; then
|
|
74
|
+
echo "Lock file updated successfully"
|
|
75
|
+
else
|
|
76
|
+
echo "::warning::Lock file unchanged - verify dependencies are correct"
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
- name: Configure git
|
|
80
|
+
run: |
|
|
81
|
+
git config user.name "all-hands-bot"
|
|
82
|
+
git config user.email "all-hands-bot@all-hands.dev"
|
|
83
|
+
|
|
84
|
+
- name: Create branch and commit
|
|
85
|
+
id: commit
|
|
86
|
+
run: |
|
|
87
|
+
VERSION="${{ inputs.version }}"
|
|
88
|
+
BRANCH_NAME="release/v$VERSION"
|
|
89
|
+
|
|
90
|
+
git checkout -b "$BRANCH_NAME" 2>/dev/null || {
|
|
91
|
+
echo "::error::Branch $BRANCH_NAME already exists. Delete it or use a different version."
|
|
92
|
+
exit 1
|
|
93
|
+
}
|
|
94
|
+
git add pyproject.toml uv.lock
|
|
95
|
+
git commit -m "chore: bump version to $VERSION"
|
|
96
|
+
git push -u origin "$BRANCH_NAME"
|
|
97
|
+
|
|
98
|
+
echo "branch=$BRANCH_NAME" >> $GITHUB_OUTPUT
|
|
99
|
+
|
|
100
|
+
- name: Create Pull Request
|
|
101
|
+
env:
|
|
102
|
+
GH_TOKEN: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC }}
|
|
103
|
+
run: |
|
|
104
|
+
VERSION="${{ inputs.version }}"
|
|
105
|
+
CURRENT="${{ steps.current.outputs.version }}"
|
|
106
|
+
|
|
107
|
+
gh pr create \
|
|
108
|
+
--title "chore: release v$VERSION" \
|
|
109
|
+
--body "## Release v$VERSION
|
|
110
|
+
|
|
111
|
+
This PR bumps the version from \`$CURRENT\` to \`$VERSION\`.
|
|
112
|
+
|
|
113
|
+
### Changes
|
|
114
|
+
- Updated \`pyproject.toml\` version to \`$VERSION\`
|
|
115
|
+
- Regenerated \`uv.lock\`
|
|
116
|
+
|
|
117
|
+
### After Merging
|
|
118
|
+
|
|
119
|
+
Once this PR is merged, create and push the release tag:
|
|
120
|
+
|
|
121
|
+
\`\`\`bash
|
|
122
|
+
git checkout main
|
|
123
|
+
git pull origin main
|
|
124
|
+
git tag $VERSION
|
|
125
|
+
git push origin $VERSION
|
|
126
|
+
\`\`\`
|
|
127
|
+
|
|
128
|
+
This will trigger:
|
|
129
|
+
- \`pypi-release.yml\` — publishes \`openhands-automation\` to PyPI
|
|
130
|
+
- \`tag-image.yml\` — tags the Docker image with \`$VERSION\`
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
*This PR was automatically created by the Prepare Release workflow.*" \
|
|
134
|
+
--base main \
|
|
135
|
+
--head "${{ steps.commit.outputs.branch }}"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Promotes each successful main build's automation image to the development
|
|
3
|
+
# environment by dispatching to OpenHands/saas-deploy, which runs the bump.
|
|
4
|
+
# Runs after the Docker workflow succeeds on main; can also be run manually
|
|
5
|
+
# (from main) to re-promote a known-good image tag.
|
|
6
|
+
|
|
7
|
+
name: Promote to development
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
inputs:
|
|
12
|
+
image-tag:
|
|
13
|
+
description: Image tag to promote (defaults to sha-<short SHA> for the selected ref)
|
|
14
|
+
required: false
|
|
15
|
+
type: string
|
|
16
|
+
workflow_run:
|
|
17
|
+
workflows: [Docker]
|
|
18
|
+
types: [completed]
|
|
19
|
+
branches: [main]
|
|
20
|
+
|
|
21
|
+
# Queue promotions so an earlier main commit deploys before a later one.
|
|
22
|
+
concurrency:
|
|
23
|
+
group: promote-to-development-automation
|
|
24
|
+
cancel-in-progress: false
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
promote:
|
|
28
|
+
# Only promote when the Docker build actually succeeded, or when run manually.
|
|
29
|
+
# The Docker workflow also runs on pull_request, and the workflow_run branches
|
|
30
|
+
# filter matches the *head* branch - a fork PR from a branch named "main"
|
|
31
|
+
# would slip through - so additionally require a push event.
|
|
32
|
+
if: >-
|
|
33
|
+
${{ github.event_name == 'workflow_dispatch' ||
|
|
34
|
+
(github.event.workflow_run.conclusion == 'success' &&
|
|
35
|
+
github.event.workflow_run.event == 'push') }}
|
|
36
|
+
runs-on: ubuntu-24.04
|
|
37
|
+
timeout-minutes: 10
|
|
38
|
+
environment: dev-deploy
|
|
39
|
+
permissions:
|
|
40
|
+
contents: read
|
|
41
|
+
steps:
|
|
42
|
+
- name: Compute image tag
|
|
43
|
+
id: tag
|
|
44
|
+
# Matches docker/metadata-action type=sha (7-char short SHA) emitted by
|
|
45
|
+
# the Docker workflow.
|
|
46
|
+
env:
|
|
47
|
+
DISPATCH_IMAGE_TAG: ${{ github.event.inputs['image-tag'] }}
|
|
48
|
+
SHA: ${{ github.event.workflow_run.head_sha || github.sha }}
|
|
49
|
+
run: |
|
|
50
|
+
if [ -n "$DISPATCH_IMAGE_TAG" ]; then
|
|
51
|
+
echo "tag=$DISPATCH_IMAGE_TAG" >> "$GITHUB_OUTPUT"
|
|
52
|
+
else
|
|
53
|
+
echo "tag=sha-${SHA::7}" >> "$GITHUB_OUTPUT"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
- name: Mint token
|
|
57
|
+
id: app-token
|
|
58
|
+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
59
|
+
with:
|
|
60
|
+
app-id: ${{ secrets.SAAS_DEPLOY_DISPATCHER_APP_ID }}
|
|
61
|
+
private-key: ${{ secrets.SAAS_DEPLOY_DISPATCHER_APP_PRIVATE_KEY }}
|
|
62
|
+
owner: OpenHands
|
|
63
|
+
repositories: saas-deploy
|
|
64
|
+
permission-contents: write
|
|
65
|
+
|
|
66
|
+
- name: Dispatch promotion to saas-deploy
|
|
67
|
+
env:
|
|
68
|
+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
69
|
+
IMAGE_TAG: ${{ steps.tag.outputs.tag }}
|
|
70
|
+
SOURCE_SHA: ${{ github.event.workflow_run.head_sha || github.sha }}
|
|
71
|
+
run: |
|
|
72
|
+
gh api /repos/OpenHands/saas-deploy/dispatches \
|
|
73
|
+
-f event_type=promote-to-development \
|
|
74
|
+
-F client_payload[release]=automation \
|
|
75
|
+
-F client_payload[tag-path]=.openhands.automation.image.tag \
|
|
76
|
+
-F client_payload[image-tag]="$IMAGE_TAG" \
|
|
77
|
+
-F client_payload[source-repo]="$GITHUB_REPOSITORY" \
|
|
78
|
+
-F client_payload[source-sha]="$SOURCE_SHA"
|
|
79
|
+
echo "Dispatched promote-to-development for automation ${IMAGE_TAG} (${SOURCE_SHA})."
|
|
80
|
+
|
|
81
|
+
- name: Annotate dispatch failure
|
|
82
|
+
if: ${{ failure() }}
|
|
83
|
+
env:
|
|
84
|
+
IMAGE_TAG: ${{ steps.tag.outputs.tag }}
|
|
85
|
+
HEAD_SHA: ${{ github.event.workflow_run.head_sha || github.sha }}
|
|
86
|
+
SOURCE_RUN_URL: ${{ github.event.workflow_run.html_url }}
|
|
87
|
+
run: |
|
|
88
|
+
image_tag="${IMAGE_TAG:-sha-${HEAD_SHA::7}}"
|
|
89
|
+
source="${SOURCE_RUN_URL:-manual workflow_dispatch run}"
|
|
90
|
+
echo "::error title=Promote to development failed::Failed to dispatch promotion of automation ${image_tag} (${HEAD_SHA}) to development. Source: ${source}"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Publishes the openhands-automation PyPI package using trusted publishing (OIDC).
|
|
3
|
+
# Triggered when a tag is pushed or manually via workflow_dispatch.
|
|
4
|
+
# Requires trusted publishing to be configured in PyPI project settings.
|
|
5
|
+
name: Publish PyPI Package
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags:
|
|
10
|
+
- '*'
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
inputs:
|
|
13
|
+
reason:
|
|
14
|
+
description: Reason for manual trigger
|
|
15
|
+
required: true
|
|
16
|
+
default: ''
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
release:
|
|
20
|
+
runs-on: ubuntu-24.04
|
|
21
|
+
permissions:
|
|
22
|
+
id-token: write
|
|
23
|
+
contents: read
|
|
24
|
+
steps:
|
|
25
|
+
- name: Checkout
|
|
26
|
+
uses: actions/checkout@v4
|
|
27
|
+
|
|
28
|
+
- name: Install uv
|
|
29
|
+
uses: astral-sh/setup-uv@v7
|
|
30
|
+
with:
|
|
31
|
+
version: latest
|
|
32
|
+
|
|
33
|
+
- name: Set up Python
|
|
34
|
+
run: uv python install 3.12
|
|
35
|
+
|
|
36
|
+
- name: Build package
|
|
37
|
+
run: uv build
|
|
38
|
+
|
|
39
|
+
- name: Publish to PyPI
|
|
40
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Automated QA validation of PR changes using OpenHands.
|
|
3
|
+
#
|
|
4
|
+
# This workflow runs only when the `qa-this` label is added to a same-repo PR.
|
|
5
|
+
# Unlike code review, the QA agent executes the changed code and posts a
|
|
6
|
+
# functional verification report.
|
|
7
|
+
name: QA Changes by OpenHands
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
pull_request:
|
|
11
|
+
types: [labeled]
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
pull-requests: write
|
|
16
|
+
issues: write
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
qa-changes:
|
|
20
|
+
# Only run for same-repo PRs (secrets are not available to forks), and
|
|
21
|
+
# only when explicitly triggered by the `qa-this` label.
|
|
22
|
+
if: |
|
|
23
|
+
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
24
|
+
github.event.label.name == 'qa-this'
|
|
25
|
+
concurrency:
|
|
26
|
+
group: qa-changes-${{ github.event.pull_request.number }}
|
|
27
|
+
cancel-in-progress: true
|
|
28
|
+
runs-on: ubuntu-24.04
|
|
29
|
+
timeout-minutes: 30
|
|
30
|
+
steps:
|
|
31
|
+
- name: Run QA Changes
|
|
32
|
+
uses: OpenHands/extensions/plugins/qa-changes@main
|
|
33
|
+
with:
|
|
34
|
+
llm-model: litellm_proxy/openai/gpt-5.5
|
|
35
|
+
llm-base-url: https://llm-proxy.app.all-hands.dev
|
|
36
|
+
max-budget: '10.0'
|
|
37
|
+
timeout-minutes: '30'
|
|
38
|
+
max-iterations: '500'
|
|
39
|
+
llm-api-key: ${{ secrets.LLM_API_KEY }}
|
|
40
|
+
github-token: ${{ secrets.OPENHANDS_BOT_GITHUB_PAT_PUBLIC || github.token }}
|
|
41
|
+
lmnr-api-key: ${{ secrets.LMNR_SKILLS_API_KEY }}
|