interlatch 0.22.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.
- interlatch-0.22.0/.github/dependabot.yml +43 -0
- interlatch-0.22.0/.github/workflows/changelog.yml +28 -0
- interlatch-0.22.0/.github/workflows/ci.yml +137 -0
- interlatch-0.22.0/.github/workflows/docs.yml +48 -0
- interlatch-0.22.0/.github/workflows/release.yml +349 -0
- interlatch-0.22.0/.gitignore +13 -0
- interlatch-0.22.0/.pre-commit-config.yaml +48 -0
- interlatch-0.22.0/.python-version +1 -0
- interlatch-0.22.0/CHANGELOG.md +767 -0
- interlatch-0.22.0/CONTRIBUTING.md +27 -0
- interlatch-0.22.0/LICENSE +21 -0
- interlatch-0.22.0/PKG-INFO +221 -0
- interlatch-0.22.0/README.ja.md +185 -0
- interlatch-0.22.0/README.md +187 -0
- interlatch-0.22.0/ROADMAP.ja.md +108 -0
- interlatch-0.22.0/ROADMAP.md +113 -0
- interlatch-0.22.0/SECURITY.md +46 -0
- interlatch-0.22.0/changelog.d/README.md +20 -0
- interlatch-0.22.0/changelog.d/interlatch-hub-image.md +3 -0
- interlatch-0.22.0/changelog.d/interlatch-migrate.md +7 -0
- interlatch-0.22.0/changelog.d/interlatch.md +5 -0
- interlatch-0.22.0/dev.sh +119 -0
- interlatch-0.22.0/docker/.dockerignore +3 -0
- interlatch-0.22.0/docker/.env.example +17 -0
- interlatch-0.22.0/docker/Caddyfile +5 -0
- interlatch-0.22.0/docker/Dockerfile +38 -0
- interlatch-0.22.0/docker/compose.yaml +81 -0
- interlatch-0.22.0/docker/wheels/.gitignore +3 -0
- interlatch-0.22.0/docs/README.md +23 -0
- interlatch-0.22.0/docs/_site/hooks.py +51 -0
- interlatch-0.22.0/docs/analysis.md +207 -0
- interlatch-0.22.0/docs/cli.md +66 -0
- interlatch-0.22.0/docs/configuration.md +125 -0
- interlatch-0.22.0/docs/dashboard.md +265 -0
- interlatch-0.22.0/docs/demo/make_demo.py +536 -0
- interlatch-0.22.0/docs/demo/record_demo.py +212 -0
- interlatch-0.22.0/docs/design/ja/learning.md +182 -0
- interlatch-0.22.0/docs/design/learning.md +198 -0
- interlatch-0.22.0/docs/development.md +170 -0
- interlatch-0.22.0/docs/devices.md +605 -0
- interlatch-0.22.0/docs/diagrams/analysis.excalidraw.svg +8 -0
- interlatch-0.22.0/docs/diagrams/architecture.excalidraw.svg +8 -0
- interlatch-0.22.0/docs/docker.md +378 -0
- interlatch-0.22.0/docs/images/demo.gif +0 -0
- interlatch-0.22.0/docs/images/home.png +0 -0
- interlatch-0.22.0/docs/images/map.png +0 -0
- interlatch-0.22.0/docs/images/palette.png +0 -0
- interlatch-0.22.0/docs/images/session.png +0 -0
- interlatch-0.22.0/docs/install.md +236 -0
- interlatch-0.22.0/docs/ja/README.md +23 -0
- interlatch-0.22.0/docs/ja/analysis.md +186 -0
- interlatch-0.22.0/docs/ja/cli.md +66 -0
- interlatch-0.22.0/docs/ja/configuration.md +125 -0
- interlatch-0.22.0/docs/ja/dashboard.md +204 -0
- interlatch-0.22.0/docs/ja/development.md +165 -0
- interlatch-0.22.0/docs/ja/devices.md +601 -0
- interlatch-0.22.0/docs/ja/docker.md +378 -0
- interlatch-0.22.0/docs/ja/install.md +223 -0
- interlatch-0.22.0/docs/ja/join-a-hub.md +106 -0
- interlatch-0.22.0/docs/ja/mcp.md +120 -0
- interlatch-0.22.0/docs/ja/moving-from-chronicle.md +92 -0
- interlatch-0.22.0/docs/ja/postgres.md +140 -0
- interlatch-0.22.0/docs/ja/privacy.md +118 -0
- interlatch-0.22.0/docs/ja/sources.md +104 -0
- interlatch-0.22.0/docs/ja/suggestions.md +261 -0
- interlatch-0.22.0/docs/ja/troubleshooting.md +128 -0
- interlatch-0.22.0/docs/ja/vscode.md +72 -0
- interlatch-0.22.0/docs/join-a-hub.md +105 -0
- interlatch-0.22.0/docs/mcp.md +123 -0
- interlatch-0.22.0/docs/moving-from-chronicle.md +92 -0
- interlatch-0.22.0/docs/postgres.md +150 -0
- interlatch-0.22.0/docs/privacy.md +123 -0
- interlatch-0.22.0/docs/sources.md +111 -0
- interlatch-0.22.0/docs/suggestions.md +272 -0
- interlatch-0.22.0/docs/troubleshooting.md +133 -0
- interlatch-0.22.0/docs/vscode.md +71 -0
- interlatch-0.22.0/mkdocs.yml +103 -0
- interlatch-0.22.0/packaging/agents-chronicle-farewell/README.md +24 -0
- interlatch-0.22.0/packaging/agents-chronicle-farewell/pyproject.toml +42 -0
- interlatch-0.22.0/packaging/icons3d/README.md +33 -0
- interlatch-0.22.0/packaging/icons3d/art.json +89 -0
- interlatch-0.22.0/packaging/icons3d/filing.html +173 -0
- interlatch-0.22.0/packaging/icons3d/loops.json +9 -0
- interlatch-0.22.0/packaging/icons3d/loops.py +86 -0
- interlatch-0.22.0/packaging/icons3d/members.js +74 -0
- interlatch-0.22.0/packaging/icons3d/render.html +65 -0
- interlatch-0.22.0/packaging/icons3d/render.py +122 -0
- interlatch-0.22.0/packaging/icons3d/scenes-more.js +166 -0
- interlatch-0.22.0/packaging/icons3d/scenes.html +205 -0
- interlatch-0.22.0/packaging/macos/Chronicle.icns +0 -0
- interlatch-0.22.0/packaging/macos/Interlatch.spec +57 -0
- interlatch-0.22.0/packaging/macos/build.sh +61 -0
- interlatch-0.22.0/packaging/macos/chronicle_app.py +22 -0
- interlatch-0.22.0/packaging/macos/entitlements.plist +11 -0
- interlatch-0.22.0/packaging/macos/icon-3d.webp +0 -0
- interlatch-0.22.0/packaging/macos/icon-blueprint-prompt.md +33 -0
- interlatch-0.22.0/packaging/macos/icon-blueprint.webp +0 -0
- interlatch-0.22.0/packaging/macos/icon.png +0 -0
- interlatch-0.22.0/packaging/macos/make_icon.py +73 -0
- interlatch-0.22.0/packaging/release.py +173 -0
- interlatch-0.22.0/pyproject.toml +100 -0
- interlatch-0.22.0/src/chronicle/__init__.py +17 -0
- interlatch-0.22.0/src/chronicle/__main__.py +3 -0
- interlatch-0.22.0/src/chronicle/access.py +93 -0
- interlatch-0.22.0/src/chronicle/agents.py +23 -0
- interlatch-0.22.0/src/chronicle/analyze.py +498 -0
- interlatch-0.22.0/src/chronicle/antigravity_parser.py +311 -0
- interlatch-0.22.0/src/chronicle/artifacts.py +621 -0
- interlatch-0.22.0/src/chronicle/bob_parser.py +259 -0
- interlatch-0.22.0/src/chronicle/cases.py +75 -0
- interlatch-0.22.0/src/chronicle/chat_import.py +325 -0
- interlatch-0.22.0/src/chronicle/chatgpt_export.py +127 -0
- interlatch-0.22.0/src/chronicle/claude_export.py +129 -0
- interlatch-0.22.0/src/chronicle/cli.py +2980 -0
- interlatch-0.22.0/src/chronicle/codex_cloud.py +138 -0
- interlatch-0.22.0/src/chronicle/codex_parser.py +753 -0
- interlatch-0.22.0/src/chronicle/config.py +627 -0
- interlatch-0.22.0/src/chronicle/connectors.py +666 -0
- interlatch-0.22.0/src/chronicle/container.py +202 -0
- interlatch-0.22.0/src/chronicle/copilot_parser.py +494 -0
- interlatch-0.22.0/src/chronicle/db.py +598 -0
- interlatch-0.22.0/src/chronicle/desktop.py +543 -0
- interlatch-0.22.0/src/chronicle/diagram.py +488 -0
- interlatch-0.22.0/src/chronicle/digest.py +194 -0
- interlatch-0.22.0/src/chronicle/export_md.py +210 -0
- interlatch-0.22.0/src/chronicle/friction.py +841 -0
- interlatch-0.22.0/src/chronicle/glossary.py +522 -0
- interlatch-0.22.0/src/chronicle/groups.py +181 -0
- interlatch-0.22.0/src/chronicle/hooks.py +169 -0
- interlatch-0.22.0/src/chronicle/hub.py +2291 -0
- interlatch-0.22.0/src/chronicle/i18n.py +37 -0
- interlatch-0.22.0/src/chronicle/i18n_ja.py +421 -0
- interlatch-0.22.0/src/chronicle/ingest.py +1190 -0
- interlatch-0.22.0/src/chronicle/install.py +590 -0
- interlatch-0.22.0/src/chronicle/instructions.py +699 -0
- interlatch-0.22.0/src/chronicle/ladder.py +244 -0
- interlatch-0.22.0/src/chronicle/learning.py +170 -0
- interlatch-0.22.0/src/chronicle/llm.py +570 -0
- interlatch-0.22.0/src/chronicle/mcp_server.py +403 -0
- interlatch-0.22.0/src/chronicle/menubar.py +771 -0
- interlatch-0.22.0/src/chronicle/migrate.py +580 -0
- interlatch-0.22.0/src/chronicle/mirror.py +453 -0
- interlatch-0.22.0/src/chronicle/news.py +110 -0
- interlatch-0.22.0/src/chronicle/notify.py +92 -0
- interlatch-0.22.0/src/chronicle/parser.py +908 -0
- interlatch-0.22.0/src/chronicle/people.py +536 -0
- interlatch-0.22.0/src/chronicle/pg.py +122 -0
- interlatch-0.22.0/src/chronicle/pricing.py +168 -0
- interlatch-0.22.0/src/chronicle/providers.py +591 -0
- interlatch-0.22.0/src/chronicle/redact.py +50 -0
- interlatch-0.22.0/src/chronicle/reviews.py +251 -0
- interlatch-0.22.0/src/chronicle/screen.py +308 -0
- interlatch-0.22.0/src/chronicle/search.py +238 -0
- interlatch-0.22.0/src/chronicle/server.py +3009 -0
- interlatch-0.22.0/src/chronicle/session_export.py +178 -0
- interlatch-0.22.0/src/chronicle/statusline.py +258 -0
- interlatch-0.22.0/src/chronicle/suggest.py +643 -0
- interlatch-0.22.0/src/chronicle/synthesize.py +365 -0
- interlatch-0.22.0/src/chronicle/systems.py +1265 -0
- interlatch-0.22.0/src/chronicle/tailnet.py +97 -0
- interlatch-0.22.0/src/chronicle/team_store.py +450 -0
- interlatch-0.22.0/src/chronicle/update.py +404 -0
- interlatch-0.22.0/src/chronicle/util.py +217 -0
- interlatch-0.22.0/src/chronicle/views.py +249 -0
- interlatch-0.22.0/src/chronicle/web/PLEX-OFL.txt +93 -0
- interlatch-0.22.0/src/chronicle/web/app.css +2350 -0
- interlatch-0.22.0/src/chronicle/web/app.js +7587 -0
- interlatch-0.22.0/src/chronicle/web/art-book.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-camera.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-chip.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-clock.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-cloud.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-coins.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-container.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-dashboard.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-dex.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-document.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-flag.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-folder.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-gateway.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-gears.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-glitch.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-globe.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-laptop.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-log.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-lumi.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-magnifier.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-pip.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-plug.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-rack.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/art-tink.webp +0 -0
- interlatch-0.22.0/src/chronicle/web/boot.js +25 -0
- interlatch-0.22.0/src/chronicle/web/favicon.png +0 -0
- interlatch-0.22.0/src/chronicle/web/i18n.js +50 -0
- interlatch-0.22.0/src/chronicle/web/icon-180.png +0 -0
- interlatch-0.22.0/src/chronicle/web/icon-192.png +0 -0
- interlatch-0.22.0/src/chronicle/web/icon-512.png +0 -0
- interlatch-0.22.0/src/chronicle/web/icon.png +0 -0
- interlatch-0.22.0/src/chronicle/web/index.html +92 -0
- interlatch-0.22.0/src/chronicle/web/ja.js +1880 -0
- interlatch-0.22.0/src/chronicle/web/learning.js +438 -0
- interlatch-0.22.0/src/chronicle/web/manifest.webmanifest +15 -0
- interlatch-0.22.0/src/chronicle/web/panel.css +175 -0
- interlatch-0.22.0/src/chronicle/web/panel.html +14 -0
- interlatch-0.22.0/src/chronicle/web/panel.js +241 -0
- interlatch-0.22.0/src/chronicle/web/plex-mono-400.woff2 +0 -0
- interlatch-0.22.0/src/chronicle/web/plex-mono-500.woff2 +0 -0
- interlatch-0.22.0/src/chronicle/web/plex-mono-600.woff2 +0 -0
- interlatch-0.22.0/src/chronicle/web/plex-sans-400.woff2 +0 -0
- interlatch-0.22.0/src/chronicle/web/plex-sans-500.woff2 +0 -0
- interlatch-0.22.0/src/chronicle/web/plex-sans-600.woff2 +0 -0
- interlatch-0.22.0/src/chronicle/web/plex-sans-700.woff2 +0 -0
- interlatch-0.22.0/src/chronicle/web/rough.js +2 -0
- interlatch-0.22.0/src/chronicle/worker.py +390 -0
- interlatch-0.22.0/tests/antigravity_fixture.py +158 -0
- interlatch-0.22.0/tests/codex_fixture.py +177 -0
- interlatch-0.22.0/tests/conftest.py +337 -0
- interlatch-0.22.0/tests/copilot_fixture.py +169 -0
- interlatch-0.22.0/tests/friction_fixture.py +111 -0
- interlatch-0.22.0/tests/test_analysis.py +288 -0
- interlatch-0.22.0/tests/test_antigravity.py +98 -0
- interlatch-0.22.0/tests/test_artifacts.py +365 -0
- interlatch-0.22.0/tests/test_bob_analysis.py +175 -0
- interlatch-0.22.0/tests/test_case_files.py +94 -0
- interlatch-0.22.0/tests/test_cases.py +169 -0
- interlatch-0.22.0/tests/test_chat_import.py +254 -0
- interlatch-0.22.0/tests/test_codex.py +156 -0
- interlatch-0.22.0/tests/test_codex_analysis.py +186 -0
- interlatch-0.22.0/tests/test_codex_cloud.py +151 -0
- interlatch-0.22.0/tests/test_container.py +184 -0
- interlatch-0.22.0/tests/test_copilot_bob.py +188 -0
- interlatch-0.22.0/tests/test_dedicated_hub.py +65 -0
- interlatch-0.22.0/tests/test_dedupe.py +142 -0
- interlatch-0.22.0/tests/test_desktop.py +149 -0
- interlatch-0.22.0/tests/test_diagram.py +155 -0
- interlatch-0.22.0/tests/test_ee_boundary.py +20 -0
- interlatch-0.22.0/tests/test_friction.py +209 -0
- interlatch-0.22.0/tests/test_glossary.py +140 -0
- interlatch-0.22.0/tests/test_group_sharing.py +150 -0
- interlatch-0.22.0/tests/test_hub.py +604 -0
- interlatch-0.22.0/tests/test_hub_accept.py +103 -0
- interlatch-0.22.0/tests/test_hub_news.py +148 -0
- interlatch-0.22.0/tests/test_hub_projects.py +379 -0
- interlatch-0.22.0/tests/test_hub_projects_listed.py +66 -0
- interlatch-0.22.0/tests/test_hub_purge.py +123 -0
- interlatch-0.22.0/tests/test_hub_sharing_race.py +67 -0
- interlatch-0.22.0/tests/test_i18n_web.py +252 -0
- interlatch-0.22.0/tests/test_ingest.py +159 -0
- interlatch-0.22.0/tests/test_instructions.py +334 -0
- interlatch-0.22.0/tests/test_integration.py +401 -0
- interlatch-0.22.0/tests/test_ladder.py +179 -0
- interlatch-0.22.0/tests/test_language.py +451 -0
- interlatch-0.22.0/tests/test_learning_glance.py +60 -0
- interlatch-0.22.0/tests/test_learning_interests.py +98 -0
- interlatch-0.22.0/tests/test_learning_web.py +203 -0
- interlatch-0.22.0/tests/test_leave_project.py +254 -0
- interlatch-0.22.0/tests/test_menubar.py +497 -0
- interlatch-0.22.0/tests/test_migrate.py +483 -0
- interlatch-0.22.0/tests/test_mirror.py +230 -0
- interlatch-0.22.0/tests/test_notify.py +152 -0
- interlatch-0.22.0/tests/test_parser.py +135 -0
- interlatch-0.22.0/tests/test_people.py +132 -0
- interlatch-0.22.0/tests/test_people_hub.py +269 -0
- interlatch-0.22.0/tests/test_people_web.py +351 -0
- interlatch-0.22.0/tests/test_project_groups.py +110 -0
- interlatch-0.22.0/tests/test_providers.py +438 -0
- interlatch-0.22.0/tests/test_queue.py +130 -0
- interlatch-0.22.0/tests/test_regressions.py +223 -0
- interlatch-0.22.0/tests/test_release.py +181 -0
- interlatch-0.22.0/tests/test_screen.py +164 -0
- interlatch-0.22.0/tests/test_security.py +367 -0
- interlatch-0.22.0/tests/test_setup.py +279 -0
- interlatch-0.22.0/tests/test_statusline.py +129 -0
- interlatch-0.22.0/tests/test_suggest.py +489 -0
- interlatch-0.22.0/tests/test_suggest_cli.py +195 -0
- interlatch-0.22.0/tests/test_systems.py +196 -0
- interlatch-0.22.0/tests/test_team.py +435 -0
- interlatch-0.22.0/tests/test_team_home.py +180 -0
- interlatch-0.22.0/tests/test_update.py +307 -0
- interlatch-0.22.0/uv.lock +1134 -0
- interlatch-0.22.0/vscode-extension/.vscodeignore +2 -0
- interlatch-0.22.0/vscode-extension/LICENSE +21 -0
- interlatch-0.22.0/vscode-extension/README.md +9 -0
- interlatch-0.22.0/vscode-extension/extension.js +329 -0
- interlatch-0.22.0/vscode-extension/media/chronicle.svg +7 -0
- interlatch-0.22.0/vscode-extension/package.json +130 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Weekly updates for the locked Python dependencies, the pinned GitHub Actions, the hub image's base and the images
|
|
2
|
+
# compose.yaml runs (security updates come sooner).
|
|
3
|
+
# A new release waits 7 days before it is proposed, so a compromised one is usually caught and pulled first.
|
|
4
|
+
version: 2
|
|
5
|
+
updates:
|
|
6
|
+
- package-ecosystem: uv
|
|
7
|
+
directory: /
|
|
8
|
+
schedule:
|
|
9
|
+
interval: weekly
|
|
10
|
+
cooldown:
|
|
11
|
+
default-days: 7
|
|
12
|
+
groups:
|
|
13
|
+
python:
|
|
14
|
+
patterns: ["*"]
|
|
15
|
+
- package-ecosystem: github-actions
|
|
16
|
+
directory: /
|
|
17
|
+
schedule:
|
|
18
|
+
interval: weekly
|
|
19
|
+
cooldown:
|
|
20
|
+
default-days: 7
|
|
21
|
+
groups:
|
|
22
|
+
actions:
|
|
23
|
+
patterns: ["*"]
|
|
24
|
+
- package-ecosystem: docker # the hub image's base (docker/Dockerfile)
|
|
25
|
+
directory: /docker
|
|
26
|
+
schedule:
|
|
27
|
+
interval: weekly
|
|
28
|
+
cooldown:
|
|
29
|
+
default-days: 7
|
|
30
|
+
labels: [dependencies, no-changelog] # a new base image is nothing users notice: no changelog line needed
|
|
31
|
+
- package-ecosystem: docker-compose # Caddy and Postgres in docker/compose.yaml
|
|
32
|
+
directory: /docker
|
|
33
|
+
schedule:
|
|
34
|
+
interval: weekly
|
|
35
|
+
cooldown:
|
|
36
|
+
default-days: 7
|
|
37
|
+
ignore: # a new major is a migration, not an update: Postgres can't read the old major's data, Caddy may change
|
|
38
|
+
# the Caddyfile
|
|
39
|
+
- dependency-name: postgres
|
|
40
|
+
update-types: ["version-update:semver-major"]
|
|
41
|
+
- dependency-name: caddy
|
|
42
|
+
update-types: ["version-update:semver-major"]
|
|
43
|
+
labels: [dependencies, no-changelog] # updating a hub downloads compose.yaml again (docs/docker.md#update)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Changelog
|
|
2
|
+
|
|
3
|
+
# A pull request that changes what ships (src/, ee/src/, docker/, vscode-extension/) adds a file to changelog.d/
|
|
4
|
+
# saying what users will notice: the Release workflow publishes the files added since the last tag as the release
|
|
5
|
+
# notes and refuses to run when there are none. A line under "## Unreleased" in CHANGELOG.md (the old way) fails the
|
|
6
|
+
# check. The no-changelog label skips it for a change users won't notice.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
pull_request:
|
|
10
|
+
types: [opened, synchronize, reopened, labeled, unlabeled]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: changelog-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
entry:
|
|
21
|
+
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-changelog') }}
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
with:
|
|
26
|
+
persist-credentials: false
|
|
27
|
+
fetch-depth: 0 # the merge commit, the base branch it merges into, and the tags (which entries are released)
|
|
28
|
+
- run: python3 packaging/release.py entry HEAD^1
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# Every pull request and every push to main: the test suite, the Postgres tests against a real database, known
|
|
4
|
+
# vulnerabilities in the locked dependencies, the pre-commit hooks (.pre-commit-config.yaml), and the hub's Docker image
|
|
5
|
+
# (docker/) built from this checkout.
|
|
6
|
+
# `test` is a required check on main.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches: [main]
|
|
11
|
+
pull_request:
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: ci-${{ github.ref }}
|
|
19
|
+
cancel-in-progress: true
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
test:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
29
|
+
- run: uv run --locked pytest -q
|
|
30
|
+
|
|
31
|
+
postgres:
|
|
32
|
+
# The team store and the mirror against a real Postgres: their tests skip without one (INTERLATCH_TEST_PG; set
|
|
33
|
+
# under its name before the rename too, CHRONICLE_TEST_PG, which a branch from before it reads)
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
services:
|
|
36
|
+
postgres:
|
|
37
|
+
image: postgres:17
|
|
38
|
+
env:
|
|
39
|
+
POSTGRES_USER: chronicle
|
|
40
|
+
POSTGRES_PASSWORD: chronicle
|
|
41
|
+
POSTGRES_DB: chronicle
|
|
42
|
+
ports: ["5432:5432"]
|
|
43
|
+
options: >-
|
|
44
|
+
--health-cmd "pg_isready -U chronicle" --health-interval 5s --health-timeout 5s --health-retries 12
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
47
|
+
with:
|
|
48
|
+
persist-credentials: false
|
|
49
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
50
|
+
- name: The Postgres tests, none of them skipped
|
|
51
|
+
run: |
|
|
52
|
+
printf 'PGHOST=127.0.0.1\nPGPORT=5432\nPGDATABASE=chronicle\nPGUSER=chronicle\nPGPASSWORD=chronicle\nPGSSLMODE=disable\n' > "$RUNNER_TEMP/pg.env"
|
|
53
|
+
chmod 600 "$RUNNER_TEMP/pg.env"
|
|
54
|
+
INTERLATCH_TEST_PG="$RUNNER_TEMP/pg.env" CHRONICLE_TEST_PG="$RUNNER_TEMP/pg.env" \
|
|
55
|
+
uv run --locked --extra postgres pytest -q -rs tests/test_team.py tests/test_mirror.py | tee "$RUNNER_TEMP/pytest.out"
|
|
56
|
+
if grep -q skipped "$RUNNER_TEMP/pytest.out"; then
|
|
57
|
+
echo "::error::a Postgres test was skipped"
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
lint:
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
65
|
+
with:
|
|
66
|
+
persist-credentials: false
|
|
67
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
68
|
+
- run: uvx pre-commit run --all-files --show-diff-on-failure
|
|
69
|
+
|
|
70
|
+
audit:
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
74
|
+
with:
|
|
75
|
+
persist-credentials: false
|
|
76
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
77
|
+
- name: pip-audit on uv.lock
|
|
78
|
+
run: |
|
|
79
|
+
uv export --frozen --all-groups --no-emit-project --format requirements.txt -o "$RUNNER_TEMP/requirements.txt"
|
|
80
|
+
uvx pip-audit --strict --disable-pip --require-hashes -r "$RUNNER_TEMP/requirements.txt"
|
|
81
|
+
|
|
82
|
+
docker:
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
86
|
+
with:
|
|
87
|
+
persist-credentials: false
|
|
88
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
89
|
+
- name: Build the hub's image from this checkout
|
|
90
|
+
run: |
|
|
91
|
+
uv build --wheel -o docker/wheels
|
|
92
|
+
docker build -t interlatch-hub:ci docker
|
|
93
|
+
- name: It refuses to start without an admin
|
|
94
|
+
run: |
|
|
95
|
+
if docker run --rm -e INTERLATCH_HUB_URL=https://hub.example.com interlatch-hub:ci; then
|
|
96
|
+
echo "::error::the hub started without an admin"
|
|
97
|
+
exit 1
|
|
98
|
+
fi
|
|
99
|
+
- name: With one, it becomes healthy and asks everyone to sign in
|
|
100
|
+
run: |
|
|
101
|
+
docker run -d --name hub -p 127.0.0.1:11524:11524 -e INTERLATCH_HUB_URL=https://hub.example.com \
|
|
102
|
+
-e INTERLATCH_ADMIN_EMAIL=ada@example.com interlatch-hub:ci
|
|
103
|
+
for _ in $(seq 1 45); do
|
|
104
|
+
[ "$(docker inspect -f '{{.State.Health.Status}}' hub)" = healthy ] && break
|
|
105
|
+
sleep 2
|
|
106
|
+
done
|
|
107
|
+
docker logs hub
|
|
108
|
+
docker inspect -f '{{.State.Health.Status}}' hub | grep -qx healthy
|
|
109
|
+
docker logs hub | grep -q '/signin?code='
|
|
110
|
+
docker logs hub | grep -q 'Interlatch hub is up: https://hub.example.com'
|
|
111
|
+
if docker logs hub 2>&1 | grep -q '127.0.0.1'; then # an editor on the server would forward it
|
|
112
|
+
echo "::error::the hub's log names 127.0.0.1"
|
|
113
|
+
exit 1
|
|
114
|
+
fi
|
|
115
|
+
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Host: hub.example.com' http://127.0.0.1:11524/api/people)
|
|
116
|
+
if [ "$code" != 401 ]; then
|
|
117
|
+
echo "::error::/api/people answered $code without a sign-in"
|
|
118
|
+
exit 1
|
|
119
|
+
fi
|
|
120
|
+
- name: A hub set up before the rename, with CHRONICLE_* variables, starts the same way
|
|
121
|
+
run: |
|
|
122
|
+
docker run -d --name old -e CHRONICLE_HUB_URL=https://old.example.com -e CHRONICLE_ADMIN_EMAIL=ada@example.com \
|
|
123
|
+
interlatch-hub:ci
|
|
124
|
+
for _ in $(seq 1 45); do
|
|
125
|
+
[ "$(docker inspect -f '{{.State.Health.Status}}' old)" = healthy ] && break
|
|
126
|
+
sleep 2
|
|
127
|
+
done
|
|
128
|
+
docker logs old
|
|
129
|
+
docker inspect -f '{{.State.Health.Status}}' old | grep -qx healthy
|
|
130
|
+
docker logs old | grep -q 'hub is up: https://old.example.com'
|
|
131
|
+
- name: compose.yaml reads a .env from before the rename, and keeps that hub's volumes
|
|
132
|
+
run: |
|
|
133
|
+
printf 'CHRONICLE_DOMAIN=old.example.com\nCHRONICLE_ADMIN_EMAIL=ada@example.com\nPOSTGRES_PASSWORD=x\n' > "$RUNNER_TEMP/old.env"
|
|
134
|
+
docker compose -f docker/compose.yaml --env-file "$RUNNER_TEMP/old.env" config > "$RUNNER_TEMP/compose.yaml"
|
|
135
|
+
grep -q 'INTERLATCH_HUB_URL: https://old.example.com' "$RUNNER_TEMP/compose.yaml"
|
|
136
|
+
grep -q 'CHRONICLE_DOMAIN: old.example.com' "$RUNNER_TEMP/compose.yaml" # what that hub's Caddyfile reads
|
|
137
|
+
grep -q 'name: chronicle_hub-data' "$RUNNER_TEMP/compose.yaml"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
# Builds the documentation (docs/ and the READMEs, mkdocs.yml) so broken links and anchors fail before they reach
|
|
4
|
+
# main. Chatixia-AI/chronicle-site publishes it at interlatch.com/docs/: when the docs change on main, this
|
|
5
|
+
# asks that site to rebuild (it also rebuilds daily). The request needs the secret SITE_DISPATCH_TOKEN, a
|
|
6
|
+
# fine-grained token with Contents: write on chronicle-site; without it the step is skipped.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches: [main]
|
|
11
|
+
paths: [docs/**, README.md, README.ja.md, mkdocs.yml, packaging/macos/icon.png, pyproject.toml, uv.lock, .github/workflows/docs.yml]
|
|
12
|
+
pull_request:
|
|
13
|
+
paths: [docs/**, README.md, README.ja.md, mkdocs.yml, .github/workflows/docs.yml]
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: docs-${{ github.ref }}
|
|
21
|
+
cancel-in-progress: true
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
build:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
28
|
+
with:
|
|
29
|
+
persist-credentials: false
|
|
30
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
31
|
+
- run: uv run --locked --only-group docs mkdocs build --strict
|
|
32
|
+
env:
|
|
33
|
+
NO_MKDOCS_2_WARNING: "1"
|
|
34
|
+
|
|
35
|
+
publish:
|
|
36
|
+
needs: build
|
|
37
|
+
if: github.event_name != 'pull_request'
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
steps:
|
|
40
|
+
- name: Ask chronicle-site to rebuild
|
|
41
|
+
env:
|
|
42
|
+
GH_TOKEN: ${{ secrets.SITE_DISPATCH_TOKEN }}
|
|
43
|
+
run: |
|
|
44
|
+
if [ -z "$GH_TOKEN" ]; then
|
|
45
|
+
echo "::notice::SITE_DISPATCH_TOKEN isn't set; chronicle-site picks up the docs on its daily build."
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
gh api repos/Chatixia-AI/chronicle-site/dispatches -f event_type=docs-updated
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Releasing is one button: Actions → Release → Run workflow on main, and pick patch, minor or major. The version
|
|
4
|
+
# lives in the git tags (hatch-vcs), so nothing is committed first. The run works out the next version from the
|
|
5
|
+
# latest vX.Y.Z tag, runs the tests, creates the tag and the GitHub release (its notes are the changelog.d/ files
|
|
6
|
+
# added since the previous tag), publishes interlatch to PyPI (trusted publishing, no token) and then agents-chronicle
|
|
7
|
+
# at the same version (its name before the rename, which installs interlatch: packaging/agents-chronicle-farewell),
|
|
8
|
+
# publishes the hub's image ghcr.io/chatixia-ai/interlatch-hub (docker/, built from that PyPI release; also as
|
|
9
|
+
# chronicle-hub, its name before the rename), attaches Interlatch-X.Y.Z-arm64.dmg, and opens a pull request that moves
|
|
10
|
+
# those files' lines into CHANGELOG.md under "## X.Y.Z (date)". The next release doesn't wait for that pull request: a
|
|
11
|
+
# file merged after the tag is simply new since it.
|
|
12
|
+
# "dry run" (the default) runs the tests and keeps the DMG as a workflow artifact, publishing nothing.
|
|
13
|
+
# Publishing a release tagged vX.Y.Z on GitHub by hand runs the same tests, PyPI and DMG jobs.
|
|
14
|
+
#
|
|
15
|
+
# PyPI takes each package only from the trusted publisher it lists for it: this repository, release.yml and the
|
|
16
|
+
# environment pypi, for interlatch and for agents-chronicle alike.
|
|
17
|
+
#
|
|
18
|
+
# The DMG is signed and notarized when these repository secrets exist, otherwise it is ad-hoc signed:
|
|
19
|
+
# MACOS_CERT_P12 base64 of the "Developer ID Application" certificate + key (.p12)
|
|
20
|
+
# MACOS_CERT_PASSWORD its export password
|
|
21
|
+
# MACOS_CODESIGN_IDENTITY e.g. "Developer ID Application: Your Name (TEAMID)"
|
|
22
|
+
# APPLE_ID, APPLE_TEAM_ID, APPLE_APP_PASSWORD for notarytool (app-specific password)
|
|
23
|
+
|
|
24
|
+
on:
|
|
25
|
+
release:
|
|
26
|
+
types: [published]
|
|
27
|
+
workflow_dispatch:
|
|
28
|
+
inputs:
|
|
29
|
+
bump:
|
|
30
|
+
description: Which part of the version goes up (dry run publishes nothing)
|
|
31
|
+
type: choice
|
|
32
|
+
options: [dry run, patch, minor, major]
|
|
33
|
+
default: dry run
|
|
34
|
+
|
|
35
|
+
permissions: {} # each job asks for what it needs
|
|
36
|
+
|
|
37
|
+
concurrency:
|
|
38
|
+
group: release # one release at a time, so two runs never pick the same version
|
|
39
|
+
cancel-in-progress: false
|
|
40
|
+
|
|
41
|
+
jobs:
|
|
42
|
+
plan:
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
permissions:
|
|
45
|
+
contents: read
|
|
46
|
+
outputs:
|
|
47
|
+
version: ${{ steps.plan.outputs.version }} # empty on a dry run
|
|
48
|
+
create: ${{ steps.plan.outputs.create }} # "true" when this run creates the release
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
51
|
+
with:
|
|
52
|
+
fetch-depth: 0 # every tag, to find the latest
|
|
53
|
+
persist-credentials: false
|
|
54
|
+
- id: plan
|
|
55
|
+
env:
|
|
56
|
+
EVENT: ${{ github.event_name }}
|
|
57
|
+
BUMP: ${{ inputs.bump }}
|
|
58
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
59
|
+
run: |
|
|
60
|
+
if [ "$EVENT" = release ]; then
|
|
61
|
+
if ! [[ "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
62
|
+
echo "::error::Release tag $RELEASE_TAG is not vX.Y.Z"
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
echo "version=${RELEASE_TAG#v}" >> "$GITHUB_OUTPUT"
|
|
66
|
+
elif [ "$BUMP" != "dry run" ]; then
|
|
67
|
+
if [ "$GITHUB_REF" != refs/heads/main ]; then
|
|
68
|
+
echo "::error::Releases come from main; this run is on $GITHUB_REF"
|
|
69
|
+
exit 1
|
|
70
|
+
fi
|
|
71
|
+
VERSION=$(python3 packaging/release.py next "$BUMP")
|
|
72
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
73
|
+
echo "create=true" >> "$GITHUB_OUTPUT"
|
|
74
|
+
echo "Releasing Interlatch **$VERSION** ($BUMP)" >> "$GITHUB_STEP_SUMMARY"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
test:
|
|
78
|
+
needs: plan
|
|
79
|
+
runs-on: macos-14
|
|
80
|
+
permissions:
|
|
81
|
+
contents: read
|
|
82
|
+
steps:
|
|
83
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
84
|
+
with:
|
|
85
|
+
fetch-depth: 0 # the version comes from the tags
|
|
86
|
+
persist-credentials: false
|
|
87
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
88
|
+
with:
|
|
89
|
+
enable-cache: false # a release never restores a cache another run could have written
|
|
90
|
+
- run: uv run --locked pytest -q
|
|
91
|
+
- name: agents-chronicle builds (the farewell job publishes it)
|
|
92
|
+
run: uv build --wheel packaging/agents-chronicle-farewell -o "$RUNNER_TEMP/farewell"
|
|
93
|
+
|
|
94
|
+
release:
|
|
95
|
+
needs: [plan, test]
|
|
96
|
+
if: needs.plan.outputs.create == 'true'
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
permissions:
|
|
99
|
+
contents: write # create the tag and the release
|
|
100
|
+
steps:
|
|
101
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
102
|
+
with:
|
|
103
|
+
fetch-depth: 0 # the notes are the changelog.d/ files added since the previous tag
|
|
104
|
+
persist-credentials: false
|
|
105
|
+
- name: Create the tag and the release
|
|
106
|
+
env:
|
|
107
|
+
GH_TOKEN: ${{ github.token }}
|
|
108
|
+
VERSION: ${{ needs.plan.outputs.version }}
|
|
109
|
+
run: |
|
|
110
|
+
python3 packaging/release.py notes "$VERSION" > "$RUNNER_TEMP/notes.md"
|
|
111
|
+
gh release create "v$VERSION" --repo "$GITHUB_REPOSITORY" --target "$GITHUB_SHA" \
|
|
112
|
+
--title "Interlatch $VERSION" --notes-file "$RUNNER_TEMP/notes.md"
|
|
113
|
+
|
|
114
|
+
pypi:
|
|
115
|
+
needs: [plan, test, release]
|
|
116
|
+
# on a published release the release job is skipped: the tag is already there
|
|
117
|
+
if: >-
|
|
118
|
+
!cancelled() && needs.plan.outputs.version != '' && needs.test.result == 'success'
|
|
119
|
+
&& contains(fromJSON('["success", "skipped"]'), needs.release.result)
|
|
120
|
+
runs-on: ubuntu-latest
|
|
121
|
+
environment: pypi
|
|
122
|
+
permissions:
|
|
123
|
+
contents: read # checkout
|
|
124
|
+
id-token: write # OIDC for PyPI trusted publishing
|
|
125
|
+
steps:
|
|
126
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
127
|
+
with:
|
|
128
|
+
ref: v${{ needs.plan.outputs.version }}
|
|
129
|
+
fetch-depth: 0 # the version comes from the tag
|
|
130
|
+
persist-credentials: false
|
|
131
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
132
|
+
with:
|
|
133
|
+
enable-cache: false # a release never restores a cache another run could have written
|
|
134
|
+
- run: uv build
|
|
135
|
+
- name: Check the build carries the release's version
|
|
136
|
+
env:
|
|
137
|
+
VERSION: ${{ needs.plan.outputs.version }}
|
|
138
|
+
run: |
|
|
139
|
+
ls dist
|
|
140
|
+
if [ ! -f "dist/interlatch-$VERSION-py3-none-any.whl" ]; then
|
|
141
|
+
echo "::error::The build is not version $VERSION"
|
|
142
|
+
exit 1
|
|
143
|
+
fi
|
|
144
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
145
|
+
|
|
146
|
+
farewell:
|
|
147
|
+
# agents-chronicle, Interlatch's name before the rename, at the same version: it installs interlatch, so a copy
|
|
148
|
+
# installed under that name keeps updating, and one from before the rename (which asks PyPI about agents-chronicle)
|
|
149
|
+
# sees the release. Published after interlatch, so it never names a version PyPI doesn't have. It carries the same
|
|
150
|
+
# chronicle/ files as interlatch, which pip needs (packaging/agents-chronicle-farewell/pyproject.toml): a wheel only.
|
|
151
|
+
needs: [plan, pypi]
|
|
152
|
+
if: ${{ !cancelled() && needs.pypi.result == 'success' }}
|
|
153
|
+
runs-on: ubuntu-latest
|
|
154
|
+
environment: pypi
|
|
155
|
+
permissions:
|
|
156
|
+
contents: read # checkout
|
|
157
|
+
id-token: write # OIDC for PyPI trusted publishing
|
|
158
|
+
env:
|
|
159
|
+
VERSION: ${{ needs.plan.outputs.version }}
|
|
160
|
+
steps:
|
|
161
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
162
|
+
with:
|
|
163
|
+
ref: v${{ needs.plan.outputs.version }}
|
|
164
|
+
persist-credentials: false
|
|
165
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
166
|
+
with:
|
|
167
|
+
enable-cache: false # a release never restores a cache another run could have written
|
|
168
|
+
- name: Wait until PyPI serves interlatch
|
|
169
|
+
run: |
|
|
170
|
+
for _ in $(seq 1 30); do
|
|
171
|
+
if python3 -m pip download --quiet --no-deps --no-cache-dir --dest "$RUNNER_TEMP/probe" \
|
|
172
|
+
"interlatch==$VERSION"; then
|
|
173
|
+
exit 0
|
|
174
|
+
fi
|
|
175
|
+
sleep 10
|
|
176
|
+
done
|
|
177
|
+
echo "::error::PyPI does not serve interlatch $VERSION after 5 minutes"
|
|
178
|
+
exit 1
|
|
179
|
+
- name: Build agents-chronicle at the release's version, pinned to the same interlatch
|
|
180
|
+
run: |
|
|
181
|
+
sed -i "s/0\.0\.0/$VERSION/g" packaging/agents-chronicle-farewell/pyproject.toml
|
|
182
|
+
uv build --wheel packaging/agents-chronicle-farewell -o dist
|
|
183
|
+
ls dist
|
|
184
|
+
if [ ! -f "dist/agents_chronicle-$VERSION-py3-none-any.whl" ]; then
|
|
185
|
+
echo "::error::The build is not version $VERSION"
|
|
186
|
+
exit 1
|
|
187
|
+
fi
|
|
188
|
+
- name: Check it carries the chronicle/ files of the interlatch on PyPI
|
|
189
|
+
run: |
|
|
190
|
+
python3 - "$RUNNER_TEMP/probe/interlatch-$VERSION-py3-none-any.whl" "dist/agents_chronicle-$VERSION-py3-none-any.whl" <<'EOF'
|
|
191
|
+
import sys, zipfile
|
|
192
|
+
def files(wheel): # chronicle/ path -> hash, from the wheel's RECORD
|
|
193
|
+
z = zipfile.ZipFile(wheel)
|
|
194
|
+
record = next(n for n in z.namelist() if n.endswith(".dist-info/RECORD"))
|
|
195
|
+
return {r.split(",")[0]: r.split(",")[1] for r in z.read(record).decode().splitlines() if r.startswith("chronicle/")}
|
|
196
|
+
if not files(sys.argv[1]) or files(sys.argv[1]) != files(sys.argv[2]):
|
|
197
|
+
sys.exit("::error::agents-chronicle's chronicle/ files differ from interlatch's")
|
|
198
|
+
EOF
|
|
199
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
200
|
+
|
|
201
|
+
image:
|
|
202
|
+
needs: [plan, pypi]
|
|
203
|
+
if: ${{ !cancelled() && needs.pypi.result == 'success' }}
|
|
204
|
+
runs-on: ubuntu-latest
|
|
205
|
+
permissions:
|
|
206
|
+
contents: read # checkout
|
|
207
|
+
packages: write # push to ghcr.io
|
|
208
|
+
env:
|
|
209
|
+
VERSION: ${{ needs.plan.outputs.version }}
|
|
210
|
+
IMAGE: ghcr.io/chatixia-ai/interlatch-hub
|
|
211
|
+
# its name before the rename: a hub whose compose.yaml still names it keeps getting each release with
|
|
212
|
+
# `docker compose pull`, which is what the dashboard tells a container to do
|
|
213
|
+
OLD_IMAGE: ghcr.io/chatixia-ai/chronicle-hub
|
|
214
|
+
steps:
|
|
215
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
216
|
+
with:
|
|
217
|
+
ref: v${{ needs.plan.outputs.version }}
|
|
218
|
+
persist-credentials: false
|
|
219
|
+
- name: Wait until PyPI serves the release
|
|
220
|
+
run: |
|
|
221
|
+
for _ in $(seq 1 30); do
|
|
222
|
+
if python3 -m pip download --quiet --no-deps --no-cache-dir --dest "$RUNNER_TEMP/probe" \
|
|
223
|
+
"interlatch==$VERSION"; then
|
|
224
|
+
exit 0
|
|
225
|
+
fi
|
|
226
|
+
sleep 10
|
|
227
|
+
done
|
|
228
|
+
echo "::error::PyPI does not serve interlatch $VERSION after 5 minutes"
|
|
229
|
+
exit 1
|
|
230
|
+
- uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
|
|
231
|
+
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
|
|
232
|
+
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
|
233
|
+
with:
|
|
234
|
+
registry: ghcr.io
|
|
235
|
+
username: ${{ github.actor }}
|
|
236
|
+
password: ${{ github.token }}
|
|
237
|
+
- uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
|
|
238
|
+
with:
|
|
239
|
+
context: docker
|
|
240
|
+
platforms: linux/amd64,linux/arm64
|
|
241
|
+
build-args: INTERLATCH_VERSION=${{ needs.plan.outputs.version }}
|
|
242
|
+
tags: |
|
|
243
|
+
${{ env.IMAGE }}:${{ needs.plan.outputs.version }}
|
|
244
|
+
${{ env.IMAGE }}:latest
|
|
245
|
+
${{ env.OLD_IMAGE }}:${{ needs.plan.outputs.version }}
|
|
246
|
+
${{ env.OLD_IMAGE }}:latest
|
|
247
|
+
push: true
|
|
248
|
+
|
|
249
|
+
macos-app:
|
|
250
|
+
needs: [plan, test, release]
|
|
251
|
+
if: >-
|
|
252
|
+
!cancelled() && needs.test.result == 'success'
|
|
253
|
+
&& contains(fromJSON('["success", "skipped"]'), needs.release.result)
|
|
254
|
+
runs-on: macos-14 # Apple silicon; PyInstaller cannot cross-build, so an Intel build needs an Intel runner
|
|
255
|
+
permissions:
|
|
256
|
+
contents: write # upload the DMG to the release
|
|
257
|
+
env:
|
|
258
|
+
HAS_CERT: ${{ secrets.MACOS_CERT_P12 != '' }}
|
|
259
|
+
VERSION: ${{ needs.plan.outputs.version }} # empty on a dry run
|
|
260
|
+
steps:
|
|
261
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
262
|
+
with:
|
|
263
|
+
ref: ${{ needs.plan.outputs.version != '' && format('v{0}', needs.plan.outputs.version) || github.sha }}
|
|
264
|
+
fetch-depth: 0 # the version comes from the tags
|
|
265
|
+
persist-credentials: false
|
|
266
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
267
|
+
with:
|
|
268
|
+
enable-cache: false # a release never restores a cache another run could have written
|
|
269
|
+
|
|
270
|
+
- name: Import signing certificate
|
|
271
|
+
if: env.HAS_CERT == 'true'
|
|
272
|
+
env:
|
|
273
|
+
MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }}
|
|
274
|
+
MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }}
|
|
275
|
+
run: |
|
|
276
|
+
KC="$RUNNER_TEMP/signing.keychain-db"
|
|
277
|
+
KCPW=$(uuidgen)
|
|
278
|
+
security create-keychain -p "$KCPW" "$KC"
|
|
279
|
+
security set-keychain-settings -lut 21600 "$KC"
|
|
280
|
+
security unlock-keychain -p "$KCPW" "$KC"
|
|
281
|
+
echo "$MACOS_CERT_P12" | base64 --decode > "$RUNNER_TEMP/cert.p12"
|
|
282
|
+
security import "$RUNNER_TEMP/cert.p12" -P "$MACOS_CERT_PASSWORD" -A -t cert -f pkcs12 -k "$KC"
|
|
283
|
+
security set-key-partition-list -S apple-tool:,apple: -k "$KCPW" "$KC"
|
|
284
|
+
security list-keychains -d user -s "$KC" $(security list-keychains -d user | tr -d '"')
|
|
285
|
+
rm "$RUNNER_TEMP/cert.p12"
|
|
286
|
+
|
|
287
|
+
- name: Build Interlatch.app and DMG
|
|
288
|
+
env:
|
|
289
|
+
INTERLATCH_CODESIGN_IDENTITY: ${{ env.HAS_CERT == 'true' && secrets.MACOS_CODESIGN_IDENTITY || '' }}
|
|
290
|
+
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
291
|
+
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
292
|
+
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
|
|
293
|
+
run: ./packaging/macos/build.sh
|
|
294
|
+
|
|
295
|
+
- name: Attach DMG to the release
|
|
296
|
+
if: env.VERSION != ''
|
|
297
|
+
env:
|
|
298
|
+
GH_TOKEN: ${{ github.token }}
|
|
299
|
+
run: gh release upload "v$VERSION" dist/Interlatch-*.dmg --repo "$GITHUB_REPOSITORY" --clobber
|
|
300
|
+
|
|
301
|
+
- name: Keep DMG as a workflow artifact
|
|
302
|
+
if: env.VERSION == ''
|
|
303
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
304
|
+
with:
|
|
305
|
+
name: Interlatch-dmg
|
|
306
|
+
path: dist/Interlatch-*.dmg
|
|
307
|
+
|
|
308
|
+
changelog:
|
|
309
|
+
needs: [plan, pypi]
|
|
310
|
+
if: needs.plan.outputs.create == 'true'
|
|
311
|
+
runs-on: ubuntu-latest
|
|
312
|
+
permissions:
|
|
313
|
+
contents: write # push the branch
|
|
314
|
+
pull-requests: write # open the pull request
|
|
315
|
+
actions: write # start CI on the branch: a push made with this token starts no workflows
|
|
316
|
+
steps:
|
|
317
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
318
|
+
with:
|
|
319
|
+
ref: main
|
|
320
|
+
fetch-depth: 0 # the tags, to find which changelog.d/ files this release took
|
|
321
|
+
persist-credentials: false
|
|
322
|
+
- name: Open a pull request that moves the release's changelog.d/ files into CHANGELOG.md
|
|
323
|
+
env:
|
|
324
|
+
GH_TOKEN: ${{ github.token }}
|
|
325
|
+
VERSION: ${{ needs.plan.outputs.version }}
|
|
326
|
+
run: |
|
|
327
|
+
BRANCH="changelog-$VERSION"
|
|
328
|
+
python3 packaging/release.py fold "$VERSION" "$(date -u +%F)" > "$RUNNER_TEMP/released.txt"
|
|
329
|
+
# one commit through the API: the new CHANGELOG.md, minus the files it took (ones merged since stay)
|
|
330
|
+
TREE=$(jq -n --rawfile changelog CHANGELOG.md --rawfile released "$RUNNER_TEMP/released.txt" \
|
|
331
|
+
--arg base "$(git rev-parse 'HEAD^{tree}')" \
|
|
332
|
+
'{base_tree: $base, tree: ([{path: "CHANGELOG.md", mode: "100644", type: "blob", content: $changelog}]
|
|
333
|
+
+ [$released | split("\n")[] | select(. != "") | {path: ., mode: "100644", type: "blob", sha: null}])}' \
|
|
334
|
+
| gh api "repos/$GITHUB_REPOSITORY/git/trees" --input - -q .sha)
|
|
335
|
+
COMMIT=$(jq -n --arg tree "$TREE" --arg parent "$(git rev-parse HEAD)" --arg message "Changelog: $VERSION" \
|
|
336
|
+
'{message: $message, tree: $tree, parents: [$parent]}' \
|
|
337
|
+
| gh api "repos/$GITHUB_REPOSITORY/git/commits" --input - -q .sha)
|
|
338
|
+
gh api "repos/$GITHUB_REPOSITORY/git/refs" -f ref="refs/heads/$BRANCH" -f sha="$COMMIT" > /dev/null
|
|
339
|
+
gh workflow run ci.yml --repo "$GITHUB_REPOSITORY" --ref "$BRANCH" # the required test check
|
|
340
|
+
if URL=$(gh pr create --repo "$GITHUB_REPOSITORY" --base main --head "$BRANCH" --title "Changelog: $VERSION" \
|
|
341
|
+
--body "Moves the changelog.d/ files released in $VERSION into CHANGELOG.md. Merge it any time: the next release doesn't wait for it."); then
|
|
342
|
+
echo "Changelog pull request: $URL" >> "$GITHUB_STEP_SUMMARY"
|
|
343
|
+
else
|
|
344
|
+
# the release is out and the next one doesn't need this, but CHANGELOG.md stays behind until it's merged
|
|
345
|
+
OPEN="https://github.com/$GITHUB_REPOSITORY/compare/main...$BRANCH?expand=1"
|
|
346
|
+
echo "Open the changelog pull request: $OPEN" >> "$GITHUB_STEP_SUMMARY"
|
|
347
|
+
echo "::error::$VERSION is released, but its changelog pull request could not be opened: $OPEN"
|
|
348
|
+
exit 1
|
|
349
|
+
fi
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Checks run on `git commit` (install once: `uvx pre-commit install`), and on every pull request in CI.
|
|
2
|
+
# Run them all by hand: `uvx pre-commit run --all-files`. Revisions are pinned to commits; `uvx pre-commit autoupdate --freeze` moves them.
|
|
3
|
+
repos:
|
|
4
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
5
|
+
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
|
|
6
|
+
hooks:
|
|
7
|
+
- id: check-merge-conflict
|
|
8
|
+
- id: check-case-conflict
|
|
9
|
+
- id: check-yaml
|
|
10
|
+
args: [--unsafe] # syntax only: mkdocs.yml uses !!python tags
|
|
11
|
+
- id: check-toml
|
|
12
|
+
- id: check-json
|
|
13
|
+
- id: check-added-large-files
|
|
14
|
+
args: [--maxkb=600]
|
|
15
|
+
- id: detect-private-key
|
|
16
|
+
- id: trailing-whitespace
|
|
17
|
+
exclude: \.excalidraw\.svg$ # written by the Excalidraw exporter
|
|
18
|
+
- id: end-of-file-fixer
|
|
19
|
+
exclude: \.excalidraw\.svg$
|
|
20
|
+
|
|
21
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
22
|
+
rev: f12be1ebaa5351c1fc76472de98db2c3446c8253 # frozen: v0.16.10
|
|
23
|
+
hooks:
|
|
24
|
+
- id: ruff-check # rules in pyproject.toml: likely bugs, not style
|
|
25
|
+
|
|
26
|
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
27
|
+
rev: 0f4b65a503cc866b9b5e62dda2020f7943b01a65 # frozen: 0.12.22
|
|
28
|
+
hooks:
|
|
29
|
+
- id: uv-lock
|
|
30
|
+
args: [--check] # pyproject.toml and uv.lock agree
|
|
31
|
+
|
|
32
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
33
|
+
rev: 83d9cd684c87d95d656c1458ef04895a7f1cbd8e # frozen: v8.30.1
|
|
34
|
+
hooks:
|
|
35
|
+
- id: gitleaks
|
|
36
|
+
|
|
37
|
+
- repo: https://github.com/zizmorcore/zizmor-pre-commit
|
|
38
|
+
rev: fa412071e4f5d44d44f9e365f4676f9df92456a2 # frozen: v1.30.1
|
|
39
|
+
hooks:
|
|
40
|
+
- id: zizmor
|
|
41
|
+
|
|
42
|
+
- repo: local
|
|
43
|
+
hooks:
|
|
44
|
+
- id: node-check
|
|
45
|
+
name: node --check (dashboard and VS Code extension JavaScript parses)
|
|
46
|
+
language: system
|
|
47
|
+
entry: node --check
|
|
48
|
+
files: ^(src/chronicle/web|vscode-extension)/.*\.js$
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|