chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
name: 🐛 Bug Report
|
||||
description: Report a bug or unexpected behavior (app is running but misbehaving)
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "needs-triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for reporting a bug! Please fill out the information below to help us understand and fix the issue.
|
||||
|
||||
**Note**: If you're having installation or setup issues, please use the "Installation Issue" template instead.
|
||||
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What did you do when it broke?
|
||||
description: Describe the steps you took that led to the bug
|
||||
placeholder: |
|
||||
1. I went to the Notebooks page
|
||||
2. I clicked on "Create New Notebook"
|
||||
3. I filled in the form and clicked "Save"
|
||||
4. Then the error occurred...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: how-broke
|
||||
attributes:
|
||||
label: How did it break?
|
||||
description: What happened that was unexpected? What did you expect to happen instead?
|
||||
placeholder: |
|
||||
Expected: The notebook should be created and I should see it in the list
|
||||
Actual: I got an error message saying "Failed to create notebook"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs-screenshots
|
||||
attributes:
|
||||
label: Logs or Screenshots
|
||||
description: |
|
||||
Please provide any error messages, logs, or screenshots that might help us understand the issue.
|
||||
|
||||
**How to get logs:**
|
||||
- Docker: `docker compose logs -f open_notebook`
|
||||
- Check browser console (F12 → Console tab)
|
||||
placeholder: |
|
||||
Paste logs here or drag and drop screenshots.
|
||||
|
||||
Error messages, stack traces, or browser console errors are very helpful!
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Open Notebook Version
|
||||
description: Which version are you using?
|
||||
options:
|
||||
- v1-latest (Docker)
|
||||
- v1-latest-single (Docker, deprecated)
|
||||
- Latest from main branch
|
||||
- Other (please specify in additional context)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: What environment are you running in?
|
||||
placeholder: |
|
||||
- OS: Ubuntu 22.04 / Windows 11 / macOS 14
|
||||
- Browser: Chrome 120
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other information that might be helpful
|
||||
placeholder: "This started happening after I upgraded to v1.5.0..."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: willing-to-contribute
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you like to work on fixing this bug?
|
||||
options:
|
||||
- label: I am a developer and would like to work on fixing this issue (pending maintainer approval)
|
||||
required: false
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
---
|
||||
**Next Steps:**
|
||||
1. A maintainer will review your bug report
|
||||
2. If you checked the box above and want to fix it, please propose your solution approach
|
||||
3. Wait for assignment before starting development
|
||||
4. See our [Contributing Guide](https://github.com/lfnovo/open-notebook/blob/main/CONTRIBUTING.md) for more details
|
||||
@@ -0,0 +1,11 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Discord Community
|
||||
url: https://discord.gg/37XJPXfz2w
|
||||
about: Get help from the community and share ideas
|
||||
- name: 🤖 Installation Assistant (ChatGPT)
|
||||
url: https://chatgpt.com/g/g-68776e2765b48191bd1bae3f30212631-open-notebook-installation-assistant
|
||||
about: CustomGPT that knows all our docs. Really useful. Try it.
|
||||
- name: 📚 Documentation
|
||||
url: https://github.com/lfnovo/open-notebook/tree/main/docs
|
||||
about: Browse our comprehensive documentation
|
||||
@@ -0,0 +1,65 @@
|
||||
name: ✨ Feature Suggestion
|
||||
description: Suggest a new feature or improvement for Open Notebook
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement", "needs-triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to suggest a feature! Your ideas help make Open Notebook better for everyone.
|
||||
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature Description
|
||||
description: What feature would you like to see added or improved?
|
||||
placeholder: "I would like to be able to..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: why-helpful
|
||||
attributes:
|
||||
label: Why would this be helpful?
|
||||
description: Explain how this feature would benefit you and other users
|
||||
placeholder: "This would help because..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: proposed-solution
|
||||
attributes:
|
||||
label: Proposed Solution (Optional)
|
||||
description: If you have ideas on how to implement this feature, please share them
|
||||
placeholder: "This could be implemented by..."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other context, screenshots, or examples that might be helpful
|
||||
placeholder: "For example, other tools do this by..."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: willing-to-contribute
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you like to work on implementing this feature?
|
||||
options:
|
||||
- label: I am a developer and would like to work on implementing this feature (pending maintainer approval)
|
||||
required: false
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
---
|
||||
**Next Steps:**
|
||||
1. A maintainer will review your feature request
|
||||
2. If approved and you checked the box above, the issue will be assigned to you
|
||||
3. Please wait for assignment before starting development
|
||||
4. See our [Contributing Guide](https://github.com/lfnovo/open-notebook/blob/main/CONTRIBUTING.md) for more details
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
name: 🔧 Installation Issue
|
||||
description: Report problems with installation, setup, or connectivity
|
||||
title: "[Install]: "
|
||||
labels: ["installation", "needs-triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## ⚠️ Before You Continue
|
||||
|
||||
**Please try these resources first:**
|
||||
|
||||
1. 🤖 **[Installation Assistant ChatGPT](https://chatgpt.com/g/g-68776e2765b48191bd1bae3f30212631-open-notebook-installation-assistant)** - Our AI assistant can help you troubleshoot most installation issues instantly!
|
||||
|
||||
2. 📚 **[Installation Guide](https://github.com/lfnovo/open-notebook/blob/main/docs/getting-started/installation.md)** - Comprehensive setup instructions
|
||||
|
||||
3. 🐋 **[Docker Deployment Guide](https://github.com/lfnovo/open-notebook/blob/main/docs/deployment/docker.md)** - Detailed Docker setup
|
||||
|
||||
4. 🦙 **Ollama Issues?** Read our [Ollama Guide](https://github.com/lfnovo/open-notebook/blob/main/docs/features/ollama.md) first
|
||||
|
||||
5. 💬 **[Discord Community](https://discord.gg/37XJPXfz2w)** - Get real-time help from the community
|
||||
|
||||
---
|
||||
|
||||
If you've tried the above and still need help, please fill out the form below with as much detail as possible.
|
||||
|
||||
- type: dropdown
|
||||
id: installation-method
|
||||
attributes:
|
||||
label: Installation Method
|
||||
description: How are you trying to install Open Notebook?
|
||||
options:
|
||||
- Docker (docker-compose - recommended)
|
||||
- Docker (single container - v1-latest-single, deprecated)
|
||||
- Local development (make start-all)
|
||||
- Other (please specify below)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue-description
|
||||
attributes:
|
||||
label: What is the issue?
|
||||
description: Describe the installation or setup problem you're experiencing
|
||||
placeholder: |
|
||||
Example: "I can't connect to the database" or "The container won't start" or "Getting 404 errors when accessing the UI"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs
|
||||
description: |
|
||||
Please provide relevant logs. **This is very important for diagnosing issues!**
|
||||
|
||||
**How to get logs:**
|
||||
- Docker single container: `docker logs open-notebook`
|
||||
- Docker Compose: `docker compose logs -f`
|
||||
- Specific service: `docker compose logs -f open_notebook`
|
||||
placeholder: |
|
||||
Paste your logs here. Include the full error message and stack trace if available.
|
||||
render: shell
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: docker-compose
|
||||
attributes:
|
||||
label: Docker Compose Configuration
|
||||
description: |
|
||||
If using Docker Compose, please paste your `docker-compose.yml` file here.
|
||||
|
||||
**⚠️ IMPORTANT: Redact any sensitive information (API keys, passwords, etc.)**
|
||||
placeholder: |
|
||||
services:
|
||||
open_notebook:
|
||||
image: lfnovo/open_notebook:v1-latest-single
|
||||
ports:
|
||||
- "8502:8502"
|
||||
- "5055:5055"
|
||||
environment:
|
||||
- OPENAI_API_KEY=sk-***REDACTED***
|
||||
...
|
||||
render: yaml
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: env-file
|
||||
attributes:
|
||||
label: Environment File
|
||||
description: |
|
||||
If using an `.env` or `docker.env` file, please paste it here.
|
||||
|
||||
**⚠️ IMPORTANT: REDACT ALL API KEYS AND PASSWORDS!**
|
||||
placeholder: |
|
||||
SURREAL_URL=ws://surrealdb:8000/rpc
|
||||
SURREAL_USER=root
|
||||
SURREAL_PASSWORD=***REDACTED***
|
||||
OPENAI_API_KEY=sk-***REDACTED***
|
||||
ANTHROPIC_API_KEY=sk-ant-***REDACTED***
|
||||
render: shell
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: system-info
|
||||
attributes:
|
||||
label: System Information
|
||||
description: Tell us about your setup
|
||||
placeholder: |
|
||||
- Operating System: Ubuntu 22.04 / Windows 11 / macOS 14
|
||||
- Docker version: `docker --version`
|
||||
- Docker Compose version: `docker compose version`
|
||||
- Architecture: amd64 / arm64 (Apple Silicon)
|
||||
- Available disk space: `df -h`
|
||||
- Available memory: `free -h` (Linux) or Activity Monitor (Mac)
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other information that might be helpful
|
||||
placeholder: |
|
||||
- Are you behind a corporate proxy or firewall?
|
||||
- Are you using a VPN?
|
||||
- Have you made any custom modifications?
|
||||
- Did this work before and suddenly break?
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please confirm you've tried these steps
|
||||
options:
|
||||
- label: I tried the [Installation Assistant ChatGPT](https://chatgpt.com/g/g-68776e2765b48191bd1bae3f30212631-open-notebook-installation-assistant)
|
||||
required: false
|
||||
- label: I read the relevant documentation ([Installation Guide](https://github.com/lfnovo/open-notebook/blob/main/docs/getting-started/installation.md) or [Ollama Guide](https://github.com/lfnovo/open-notebook/blob/main/docs/features/ollama.md))
|
||||
required: false
|
||||
- label: I searched existing issues to see if this was already reported
|
||||
required: true
|
||||
- label: I redacted all sensitive information (API keys, passwords, etc.)
|
||||
required: true
|
||||
@@ -0,0 +1,174 @@
|
||||
# Release Process
|
||||
|
||||
Open Notebook uses a flow-driven release process. Work moves from `ready`
|
||||
issues into pull requests, pull requests merge to `main`, and maintainers cut a
|
||||
version when the branch has enough validated change to ship.
|
||||
|
||||
This document covers both the **mechanics** (how to cut, build and publish) and
|
||||
the **confidence process** (how we know a release is good before users get it).
|
||||
It was redesigned during the v1.11.0 release ([ADR-005](../docs/7-DEVELOPMENT/decisions/ADR-005-release-confidence-process.md)).
|
||||
|
||||
## Release Model
|
||||
|
||||
- Patch releases ship backwards-compatible fixes.
|
||||
- Minor releases ship backwards-compatible features and improvements.
|
||||
- Major releases are planned with a milestone when they include breaking
|
||||
changes or migrations that need user coordination.
|
||||
- Use the `in-dev-build` label for changes available in development images and
|
||||
`released` for shipped work. (The `released` label was recreated during
|
||||
v1.12.0 — it had been dropped from the curated label taxonomy while this
|
||||
document still required it. If a label this document references is missing,
|
||||
recreate it rather than skipping the step.)
|
||||
|
||||
## Normal Flow
|
||||
|
||||
1. Triage issues into `ready` once the scope and design are clear.
|
||||
2. Implement each change in a focused pull request linked to the approved issue.
|
||||
3. Merge the pull request after review and required checks pass.
|
||||
4. Let the development build publish the `v1-dev` image from `main`.
|
||||
5. Cut a stable release when `main` has a coherent set of changes ready for
|
||||
users — following the confidence process below.
|
||||
|
||||
## The Confidence Process
|
||||
|
||||
Releases keep getting bigger; ad-hoc verification does not scale. Before
|
||||
cutting, run this sequence:
|
||||
|
||||
### 0. Changelog audit
|
||||
|
||||
Diff `git log <last-tag>..main` against the `[Unreleased]` section of the
|
||||
CHANGELOG. Every merged PR must be represented (entries reference the issue
|
||||
number when one exists, the PR number otherwise). The changelog is the input
|
||||
for both the test plan and the release notes — close the gaps first, via PR.
|
||||
|
||||
### 1. Risk-based test matrix
|
||||
|
||||
Build a matrix from the actual release diff: each change → what it can break
|
||||
and for whom → which bucket tests it. Pay special attention to
|
||||
**"does the protection break legitimate use?"** for security changes (e.g. an
|
||||
SSRF guard vs. self-hosted Ollama on localhost) and to anything a reverse
|
||||
proxy, an upgrade, or a big upload would exercise.
|
||||
|
||||
Buckets:
|
||||
|
||||
- **A — automated, high confidence, run now**: full backend suite, frontend
|
||||
lint/tests/production build, the smoke-e2e agent (full API happy path + UI
|
||||
verification), targeted regression probes for the release's specific risks,
|
||||
dependency audit.
|
||||
- **B — automatable with investment**: decide per item whether to build the
|
||||
muscle now (it compounds: the image gate below started as a bucket-B item)
|
||||
or verify manually this once.
|
||||
- **C — needs the release owner**: real provider credentials, real TTS podcast
|
||||
generation, visual/UX judgment, and the final check of the pushed image.
|
||||
|
||||
### 2. The image gate — test the artifact, not the repo
|
||||
|
||||
A green suite on `main` is not a working image. Run:
|
||||
|
||||
```bash
|
||||
make docker-build-local # builds <version> + local tags
|
||||
make release-test TAG=<new> OLD_TAG=<previous>
|
||||
```
|
||||
|
||||
This runs two scenarios against real containers (`scripts/release-test/`):
|
||||
|
||||
- **Fresh install**: empty DB → migrations on boot → in-image worker processes
|
||||
a source → API/frontend/nginx-proxied checks.
|
||||
- **Upgrade**: boot the *published* previous image, seed data, swap to the new
|
||||
image on the same volume → migrations apply, data survives.
|
||||
|
||||
Caveat: `docker-build-local` tags with the current `pyproject.toml` version —
|
||||
`docker pull` the genuine previous tag before the upgrade test so you are not
|
||||
comparing the new build against itself.
|
||||
|
||||
### 3. Fix loop with a re-test policy
|
||||
|
||||
Findings become focused PRs through the normal review flow. After each merge:
|
||||
the cheap suite always re-runs; smoke/image gates re-run only if the fix
|
||||
touches what they cover; manual verification is not repeated unless the fix
|
||||
touches what was manually verified. Pre-existing bugs found along the way that
|
||||
are not release regressions become backlog issues instead of scope creep.
|
||||
|
||||
## Cutting A Stable Release
|
||||
|
||||
1. Confirm `main` is green and the confidence process above has run.
|
||||
2. Open the **cut PR**: bump `pyproject.toml`, date the `[Unreleased]` section
|
||||
as `[<version>] - <date>`.
|
||||
3. After merge: `make tag`.
|
||||
4. Build and push version images **via CI** (it holds the registry
|
||||
credentials): trigger the *Build and Release* workflow with
|
||||
`push_latest=false`. Local `make docker-push` also works but requires
|
||||
`docker login` on both registries.
|
||||
5. **Verify the pushed image** (bucket C, final gate): run it locally with
|
||||
`make release-stack TAG=<version> [DUMP=<dev-data-dump>]` — a browsable,
|
||||
isolated stack, optionally with a copy of real data — and walk the core
|
||||
flows in the browser.
|
||||
6. Publish the GitHub release. A non-prerelease publication triggers the
|
||||
workflow again and pushes the `v1-latest` tags automatically.
|
||||
7. Verify the `v1-latest` manifests on Docker Hub and GHCR (both arches, both
|
||||
variants), and mark shipped issues with `released`.
|
||||
|
||||
## Communication
|
||||
|
||||
Release notes follow this structure (see v1.11.0 as the reference):
|
||||
|
||||
1. One-line verdict + upgrade recommendation.
|
||||
2. Sections: Security, Features, Performance, Notable fixes.
|
||||
3. **Behavior changes for self-hosters** — anything that can require a config
|
||||
tweak on upgrade gets an explicit callout.
|
||||
4. **Thanks** — credit every contributor by handle with what they shipped
|
||||
(collect via `git log <last-tag>..<tag>` + `gh pr view` for handles), plus
|
||||
the issue reporters collectively. Never skip this section.
|
||||
|
||||
Announce on Discord after `v1-latest` is live.
|
||||
|
||||
## Retro
|
||||
|
||||
Close every release by asking: what should improve in this process? Apply the
|
||||
accepted improvements immediately — update this document, the scripts under
|
||||
`scripts/release-test/`, and the decision log while the context is fresh.
|
||||
|
||||
## Docker Image Publishing (reference)
|
||||
|
||||
| Command | What it does | Updates latest? |
|
||||
|---------|--------------|-----------------|
|
||||
| `make docker-build-local` | Build for current platform only (tags `<version>` + `local`) | No registry push |
|
||||
| CI *Build and Release* (`push_latest=false`) | Push version tags via CI credentials | ❌ No |
|
||||
| GitHub release published (non-prerelease) | CI pushes version + `v1-latest` | ✅ Yes |
|
||||
| `make docker-push` / `docker-push-latest` | Local equivalents (need `docker login`) | ❌ / ✅ |
|
||||
| `make tag` | Create and push a git tag matching `pyproject.toml` | — |
|
||||
|
||||
- **Platforms:** `linux/amd64`, `linux/arm64`
|
||||
- **Registries:** Docker Hub + GitHub Container Registry
|
||||
- **Image variants:** regular + single-container (`-single`). Both are built
|
||||
from the same `Dockerfile`: regular is the default/`runtime` target, single
|
||||
is `--target single`
|
||||
- **Version source:** `pyproject.toml`
|
||||
- Build issues: `docker builder prune`, then `make docker-buildx-reset`
|
||||
|
||||
## Known Gotchas
|
||||
|
||||
- **RC stack on non-default ports needs `API_URL`** or the browser talks to
|
||||
`host:5055` — on a dev machine that is the development API (data crossover).
|
||||
`rc-stack.sh` sets it; remember this for any custom setup.
|
||||
- **Containerized app + host services**: credentials pointing at local
|
||||
services (Ollama, LM Studio) need `http://host.docker.internal:<port>`.
|
||||
- **SurrealDB import**: `OVERWRITE` goes after the type keyword
|
||||
(`DEFINE FIELD OVERWRITE …`), and the exporter can leak a log line into the
|
||||
dump — `rc-stack.sh` handles both.
|
||||
- **Multiple local SurrealDB instances**: check which one the dev `.env`
|
||||
actually points at (`SURREAL_URL`) before exporting data.
|
||||
- **Dev-machine ports may belong to other projects**: check who owns
|
||||
3000/5055/8000 (`lsof -nP -iTCP:<port> -sTCP:LISTEN` + the process cwd)
|
||||
before starting or killing anything. The frontend runs fine on an alternate
|
||||
port for smoke testing (`PORT=3001 npm run dev`) — pass the URL to the
|
||||
smoke agent.
|
||||
- **Manual error-path checklist items must be validated against the code
|
||||
first**: some "missing configuration" scenarios are deliberate fallbacks,
|
||||
not errors (e.g. transformation and tools defaults fall back to the chat
|
||||
default). Confirm the expected behavior in the provisioning code before
|
||||
putting "should show an error" on the bucket-C checklist.
|
||||
- **The test suite runs against the live dev database** when a developer
|
||||
`.env` is loaded. During bucket A, snapshot record counts per table before
|
||||
and after the suite (e.g. credentials count) — a diff means a test is
|
||||
leaking writes (this caught 48 leaked `Test` credentials in v1.12.0).
|
||||
@@ -0,0 +1,109 @@
|
||||
## Description
|
||||
|
||||
<!-- Provide a clear and concise description of what this PR does -->
|
||||
|
||||
## Related Issue
|
||||
|
||||
<!-- Non-trivial PRs (features, architecture changes) must link an approved issue.
|
||||
Small obvious fixes (typo, docs, tiny bug) don't need one — write "N/A (small fix)" below.
|
||||
Sizeable change without an issue? Mark this PR as draft and create the issue first. -->
|
||||
|
||||
Fixes #<!-- issue number, or "N/A (small fix)" -->
|
||||
|
||||
## Type of Change
|
||||
|
||||
<!-- Mark the relevant option with an "x" -->
|
||||
|
||||
- [ ] Bug fix (non-breaking change that fixes an issue)
|
||||
- [ ] New feature (non-breaking change that adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] Documentation update
|
||||
- [ ] Code refactoring (no functional changes)
|
||||
- [ ] Performance improvement
|
||||
- [ ] Test coverage improvement
|
||||
|
||||
## How Has This Been Tested?
|
||||
|
||||
<!-- Describe the tests you ran and/or how you verified your changes work -->
|
||||
|
||||
- [ ] Tested locally with Docker
|
||||
- [ ] Tested locally with development setup
|
||||
- [ ] Added new unit tests
|
||||
- [ ] Existing tests pass (`uv run pytest`)
|
||||
- [ ] Manual testing performed (describe below)
|
||||
|
||||
**Test Details:**
|
||||
<!-- Describe your testing approach -->
|
||||
|
||||
## Design Alignment
|
||||
|
||||
<!-- This section helps ensure your PR aligns with our project vision -->
|
||||
|
||||
**Which design principles does this PR support?** (See [VISION.md](https://github.com/lfnovo/open-notebook/blob/main/VISION.md))
|
||||
|
||||
- [ ] Privacy First
|
||||
- [ ] Simplicity Over Features
|
||||
- [ ] API-First Architecture
|
||||
- [ ] Multi-Provider Flexibility
|
||||
- [ ] Extensibility Through Standards
|
||||
- [ ] Async-First for Performance
|
||||
|
||||
**Explanation:**
|
||||
<!-- Brief explanation of how your changes align with these principles -->
|
||||
|
||||
## Checklist
|
||||
|
||||
<!-- Mark completed items with an "x" -->
|
||||
|
||||
### Code Quality
|
||||
- [ ] My code follows PEP 8 style guidelines (Python)
|
||||
- [ ] My code follows TypeScript best practices (Frontend)
|
||||
- [ ] I have added type hints to my code (Python)
|
||||
- [ ] I have added JSDoc comments where appropriate (TypeScript)
|
||||
- [ ] I have performed a self-review of my code
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||
- [ ] My changes generate no new warnings or errors
|
||||
|
||||
### Testing
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] New and existing unit tests pass locally with my changes
|
||||
- [ ] I ran linting: `make ruff` or `ruff check . --fix`
|
||||
- [ ] I ran type checking: `make lint` or `uv run python -m mypy .`
|
||||
|
||||
### Documentation
|
||||
- [ ] I have updated the relevant documentation in `/docs` (if applicable)
|
||||
- [ ] I have added/updated docstrings for new/modified functions
|
||||
- [ ] I have updated the API documentation (if API changes were made)
|
||||
- [ ] I have added comments to complex logic
|
||||
|
||||
### Database Changes
|
||||
- [ ] I have created migration scripts for any database schema changes (in `/migrations`)
|
||||
- [ ] Migration includes both up and down scripts
|
||||
- [ ] Migration has been tested locally
|
||||
|
||||
### Breaking Changes
|
||||
- [ ] This PR includes breaking changes
|
||||
- [ ] I have documented the migration path for users
|
||||
- [ ] I have updated MIGRATION.md (if applicable)
|
||||
|
||||
## Screenshots (if applicable)
|
||||
|
||||
<!-- Add screenshots for UI changes -->
|
||||
|
||||
## Additional Context
|
||||
|
||||
<!-- Add any other context about the PR here -->
|
||||
|
||||
## Pre-Submission Verification
|
||||
|
||||
Before submitting, please verify:
|
||||
|
||||
- [ ] I have read [CONTRIBUTING.md](https://github.com/lfnovo/open-notebook/blob/main/docs/7-DEVELOPMENT/contributing.md)
|
||||
- [ ] I have read [VISION.md](https://github.com/lfnovo/open-notebook/blob/main/VISION.md)
|
||||
- [ ] This PR addresses an approved issue assigned to me, **or** it's a small obvious fix (typo, docs, tiny bug) that doesn't need one — for anything bigger without an issue, mark this PR as draft and open the issue (triage takes 1–2 days)
|
||||
- [ ] I have not included unrelated changes in this PR
|
||||
- [ ] My PR title follows conventional commits format (e.g., "feat: add user authentication")
|
||||
|
||||
---
|
||||
|
||||
**Thank you for contributing to Open Notebook!** 🎉
|
||||
@@ -0,0 +1,300 @@
|
||||
name: Build and Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
push_latest:
|
||||
description: 'Also push v1-latest tags'
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
GHCR_IMAGE: ghcr.io/lfnovo/open-notebook
|
||||
DOCKERHUB_IMAGE: lfnovo/open_notebook
|
||||
|
||||
jobs:
|
||||
extract-version:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
has_dockerhub_secrets: ${{ steps.check.outputs.has_dockerhub_secrets }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Extract version from pyproject.toml
|
||||
id: version
|
||||
run: |
|
||||
VERSION=$(grep -m1 '^version = ' pyproject.toml | cut -d'"' -f2)
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "Extracted version: $VERSION"
|
||||
|
||||
- name: Check for Docker Hub credentials
|
||||
id: check
|
||||
env:
|
||||
SECRET_DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
SECRET_DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
run: |
|
||||
if [[ -n ""$SECRET_DOCKER_USERNAME"" && -n ""$SECRET_DOCKER_PASSWORD"" ]]; then
|
||||
echo "has_dockerhub_secrets=true" >> $GITHUB_OUTPUT
|
||||
echo "Docker Hub credentials available"
|
||||
else
|
||||
echo "has_dockerhub_secrets=false" >> $GITHUB_OUTPUT
|
||||
echo "Docker Hub credentials not available - will only push to GHCR"
|
||||
fi
|
||||
|
||||
build-regular:
|
||||
needs: extract-version
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Free up disk space
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force
|
||||
df -h
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
if: needs.extract-version.outputs.has_dockerhub_secrets == 'true'
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-regular-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-regular-
|
||||
|
||||
- name: Prepare Docker tags for regular build
|
||||
id: tags-regular
|
||||
env:
|
||||
ENV_GHCR_IMAGE: ${{ env.GHCR_IMAGE }}
|
||||
GITHUB_EVENT_INPUTS_PUSH_LATEST: ${{ github.event.inputs.push_latest }}
|
||||
GITHUB_EVENT_NAME: ${{ github.event_name }}
|
||||
GITHUB_EVENT_RELEASE_PRERELEASE: ${{ github.event.release.prerelease }}
|
||||
ENV_DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_IMAGE }}
|
||||
run: |
|
||||
TAGS=""$ENV_GHCR_IMAGE":${{ needs.extract-version.outputs.version }}"
|
||||
|
||||
# Determine if we should push latest tags
|
||||
PUSH_LATEST=""$GITHUB_EVENT_INPUTS_PUSH_LATEST""
|
||||
if [[ -z "$PUSH_LATEST" ]]; then
|
||||
PUSH_LATEST="false"
|
||||
fi
|
||||
|
||||
# Add GHCR latest tag if requested or for non-prerelease releases
|
||||
if [[ "$PUSH_LATEST" == "true" ]] || [[ ""$GITHUB_EVENT_NAME"" == "release" && ""$GITHUB_EVENT_RELEASE_PRERELEASE"" != "true" ]]; then
|
||||
TAGS="${TAGS},"$ENV_GHCR_IMAGE":v1-latest"
|
||||
fi
|
||||
|
||||
# Add Docker Hub tags if credentials available
|
||||
if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then
|
||||
TAGS="${TAGS},"$ENV_DOCKERHUB_IMAGE":${{ needs.extract-version.outputs.version }}"
|
||||
|
||||
if [[ "$PUSH_LATEST" == "true" ]] || [[ ""$GITHUB_EVENT_NAME"" == "release" && ""$GITHUB_EVENT_RELEASE_PRERELEASE"" != "true" ]]; then
|
||||
TAGS="${TAGS},"$ENV_DOCKERHUB_IMAGE":v1-latest"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "tags=${TAGS}" >> $GITHUB_OUTPUT
|
||||
echo "Generated tags: ${TAGS}"
|
||||
|
||||
- name: Build and push regular image
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
target: runtime
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.tags-regular.outputs.tags }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
|
||||
|
||||
- name: Move cache
|
||||
run: |
|
||||
rm -rf /tmp/.buildx-cache
|
||||
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
||||
|
||||
build-single:
|
||||
needs: extract-version
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Free up disk space
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force
|
||||
df -h
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
if: needs.extract-version.outputs.has_dockerhub_secrets == 'true'
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: /tmp/.buildx-cache-single
|
||||
key: ${{ runner.os }}-buildx-single-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-single-
|
||||
|
||||
- name: Prepare Docker tags for single build
|
||||
id: tags-single
|
||||
env:
|
||||
ENV_GHCR_IMAGE: ${{ env.GHCR_IMAGE }}
|
||||
GITHUB_EVENT_INPUTS_PUSH_LATEST: ${{ github.event.inputs.push_latest }}
|
||||
GITHUB_EVENT_NAME: ${{ github.event_name }}
|
||||
GITHUB_EVENT_RELEASE_PRERELEASE: ${{ github.event.release.prerelease }}
|
||||
ENV_DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_IMAGE }}
|
||||
run: |
|
||||
TAGS=""$ENV_GHCR_IMAGE":${{ needs.extract-version.outputs.version }}-single"
|
||||
|
||||
# Determine if we should push latest tags
|
||||
PUSH_LATEST=""$GITHUB_EVENT_INPUTS_PUSH_LATEST""
|
||||
if [[ -z "$PUSH_LATEST" ]]; then
|
||||
PUSH_LATEST="false"
|
||||
fi
|
||||
|
||||
# Add GHCR latest tag if requested or for non-prerelease releases
|
||||
if [[ "$PUSH_LATEST" == "true" ]] || [[ ""$GITHUB_EVENT_NAME"" == "release" && ""$GITHUB_EVENT_RELEASE_PRERELEASE"" != "true" ]]; then
|
||||
TAGS="${TAGS},"$ENV_GHCR_IMAGE":v1-latest-single"
|
||||
fi
|
||||
|
||||
# Add Docker Hub tags if credentials available
|
||||
if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then
|
||||
TAGS="${TAGS},"$ENV_DOCKERHUB_IMAGE":${{ needs.extract-version.outputs.version }}-single"
|
||||
|
||||
if [[ "$PUSH_LATEST" == "true" ]] || [[ ""$GITHUB_EVENT_NAME"" == "release" && ""$GITHUB_EVENT_RELEASE_PRERELEASE"" != "true" ]]; then
|
||||
TAGS="${TAGS},"$ENV_DOCKERHUB_IMAGE":v1-latest-single"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "tags=${TAGS}" >> $GITHUB_OUTPUT
|
||||
echo "Generated tags: ${TAGS}"
|
||||
|
||||
- name: Build and push single-container image
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
target: single
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.tags-single.outputs.tags }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache-single
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache-single-new,mode=max
|
||||
|
||||
- name: Move cache
|
||||
run: |
|
||||
rm -rf /tmp/.buildx-cache-single
|
||||
mv /tmp/.buildx-cache-single-new /tmp/.buildx-cache-single
|
||||
|
||||
summary:
|
||||
needs: [extract-version, build-regular, build-single]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
- name: Build Summary
|
||||
env:
|
||||
GITHUB_EVENT_INPUTS_PUSH_LATEST_____FALSE_: ${{ github.event.inputs.push_latest || 'false' }}
|
||||
ENV_GHCR_IMAGE: ${{ env.GHCR_IMAGE }}
|
||||
ENV_DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_IMAGE }}
|
||||
GITHUB_EVENT_INPUTS_PUSH_LATEST: ${{ github.event.inputs.push_latest }}
|
||||
run: |
|
||||
echo "## Build Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Version:** ${{ needs.extract-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Push v1-Latest:** "$GITHUB_EVENT_INPUTS_PUSH_LATEST_____FALSE_"" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Registries:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "✅ **GHCR:** \`"$ENV_GHCR_IMAGE"\`" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then
|
||||
echo "✅ **Docker Hub:** \`"$ENV_DOCKERHUB_IMAGE"\`" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "⏭️ **Docker Hub:** Skipped (credentials not configured)" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Images Built:" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [[ "${{ needs.build-regular.result }}" == "success" ]]; then
|
||||
echo "✅ **Regular (GHCR):** \`"$ENV_GHCR_IMAGE":${{ needs.extract-version.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ ""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" == "true" ]]; then
|
||||
echo "✅ **Regular v1-Latest (GHCR):** \`"$ENV_GHCR_IMAGE":v1-latest\`" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then
|
||||
echo "✅ **Regular (Docker Hub):** \`"$ENV_DOCKERHUB_IMAGE":${{ needs.extract-version.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ ""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" == "true" ]]; then
|
||||
echo "✅ **Regular v1-Latest (Docker Hub):** \`"$ENV_DOCKERHUB_IMAGE":v1-latest\`" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
fi
|
||||
elif [[ "${{ needs.build-regular.result }}" == "skipped" ]]; then
|
||||
echo "⏭️ **Regular:** Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **Regular:** Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [[ "${{ needs.build-single.result }}" == "success" ]]; then
|
||||
echo "✅ **Single (GHCR):** \`"$ENV_GHCR_IMAGE":${{ needs.extract-version.outputs.version }}-single\`" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ ""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" == "true" ]]; then
|
||||
echo "✅ **Single v1-Latest (GHCR):** \`"$ENV_GHCR_IMAGE":v1-latest-single\`" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then
|
||||
echo "✅ **Single (Docker Hub):** \`"$ENV_DOCKERHUB_IMAGE":${{ needs.extract-version.outputs.version }}-single\`" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ ""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" == "true" ]]; then
|
||||
echo "✅ **Single v1-Latest (Docker Hub):** \`"$ENV_DOCKERHUB_IMAGE":v1-latest-single\`" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
fi
|
||||
elif [[ "${{ needs.build-single.result }}" == "skipped" ]]; then
|
||||
echo "⏭️ **Single:** Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **Single:** Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Platforms:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- linux/amd64" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- linux/arm64" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -0,0 +1,275 @@
|
||||
name: Development Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'docs/**'
|
||||
- 'notebooks/**'
|
||||
- '.github/workflows/claude*.yml'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
platform:
|
||||
description: 'Platform to build'
|
||||
required: true
|
||||
default: 'linux/amd64'
|
||||
type: choice
|
||||
options:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
- linux/amd64,linux/arm64
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
GHCR_IMAGE: ghcr.io/lfnovo/open-notebook
|
||||
DOCKERHUB_IMAGE: lfnovo/open_notebook
|
||||
|
||||
jobs:
|
||||
extract-version:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
has_dockerhub_secrets: ${{ steps.check.outputs.has_dockerhub_secrets }}
|
||||
is_push_to_main: ${{ steps.check.outputs.is_push_to_main }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Extract version from pyproject.toml
|
||||
id: version
|
||||
run: |
|
||||
VERSION=$(grep -m1 '^version = ' pyproject.toml | cut -d'"' -f2)
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "Extracted version: $VERSION"
|
||||
|
||||
- name: Check environment
|
||||
id: check
|
||||
env:
|
||||
SECRET_DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
SECRET_DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
run: |
|
||||
# Check for Docker Hub credentials
|
||||
if [[ -n "$SECRET_DOCKER_USERNAME" && -n "$SECRET_DOCKER_PASSWORD" ]]; then
|
||||
echo "has_dockerhub_secrets=true" >> $GITHUB_OUTPUT
|
||||
echo "Docker Hub credentials available"
|
||||
else
|
||||
echo "has_dockerhub_secrets=false" >> $GITHUB_OUTPUT
|
||||
echo "Docker Hub credentials not available"
|
||||
fi
|
||||
|
||||
# Check if this is a push to main (not a PR)
|
||||
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/main" ]]; then
|
||||
echo "is_push_to_main=true" >> $GITHUB_OUTPUT
|
||||
echo "This is a push to main - will publish v1-dev tags"
|
||||
else
|
||||
echo "is_push_to_main=false" >> $GITHUB_OUTPUT
|
||||
echo "This is a PR or manual run - test build only"
|
||||
fi
|
||||
|
||||
build-regular:
|
||||
needs: extract-version
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Free up disk space
|
||||
if: needs.extract-version.outputs.is_push_to_main == 'true'
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force
|
||||
df -h
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: needs.extract-version.outputs.is_push_to_main == 'true'
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
if: needs.extract-version.outputs.is_push_to_main == 'true' && needs.extract-version.outputs.has_dockerhub_secrets == 'true'
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: /tmp/.buildx-cache-dev
|
||||
key: ${{ runner.os }}-buildx-dev-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-dev-
|
||||
|
||||
- name: Prepare Docker tags
|
||||
id: tags
|
||||
run: |
|
||||
if [[ "${{ needs.extract-version.outputs.is_push_to_main }}" == "true" ]]; then
|
||||
# Push to main: build and push v1-dev tags
|
||||
TAGS="${{ env.GHCR_IMAGE }}:v1-dev"
|
||||
if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then
|
||||
TAGS="${TAGS},${{ env.DOCKERHUB_IMAGE }}:v1-dev"
|
||||
fi
|
||||
echo "tags=${TAGS}" >> $GITHUB_OUTPUT
|
||||
echo "push=true" >> $GITHUB_OUTPUT
|
||||
echo "platforms=linux/amd64,linux/arm64" >> $GITHUB_OUTPUT
|
||||
else
|
||||
# PR or manual: test build only
|
||||
echo "tags=${{ env.DOCKERHUB_IMAGE }}:${{ needs.extract-version.outputs.version }}-dev" >> $GITHUB_OUTPUT
|
||||
echo "push=false" >> $GITHUB_OUTPUT
|
||||
echo "platforms=${{ github.event.inputs.platform || 'linux/amd64' }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Build and push regular image
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
target: runtime
|
||||
platforms: ${{ steps.tags.outputs.platforms }}
|
||||
push: ${{ steps.tags.outputs.push }}
|
||||
tags: ${{ steps.tags.outputs.tags }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache-dev
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache-dev-new,mode=max
|
||||
|
||||
- name: Move cache
|
||||
run: |
|
||||
rm -rf /tmp/.buildx-cache-dev
|
||||
mv /tmp/.buildx-cache-dev-new /tmp/.buildx-cache-dev
|
||||
|
||||
build-single:
|
||||
needs: extract-version
|
||||
# Only build single image on push to main
|
||||
if: needs.extract-version.outputs.is_push_to_main == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Free up disk space
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force
|
||||
df -h
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
if: needs.extract-version.outputs.has_dockerhub_secrets == 'true'
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: /tmp/.buildx-cache-dev-single
|
||||
key: ${{ runner.os }}-buildx-dev-single-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-dev-single-
|
||||
|
||||
- name: Prepare Docker tags
|
||||
id: tags
|
||||
run: |
|
||||
TAGS="${{ env.GHCR_IMAGE }}:v1-dev-single"
|
||||
if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then
|
||||
TAGS="${TAGS},${{ env.DOCKERHUB_IMAGE }}:v1-dev-single"
|
||||
fi
|
||||
echo "tags=${TAGS}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and push single-container image
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
target: single
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.tags.outputs.tags }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache-dev-single
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache-dev-single-new,mode=max
|
||||
|
||||
- name: Move cache
|
||||
run: |
|
||||
rm -rf /tmp/.buildx-cache-dev-single
|
||||
mv /tmp/.buildx-cache-dev-single-new /tmp/.buildx-cache-dev-single
|
||||
|
||||
summary:
|
||||
needs: [extract-version, build-regular, build-single]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
- name: Development Build Summary
|
||||
run: |
|
||||
echo "## Development Build Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Version:** ${{ needs.extract-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Event:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Push to Main:** ${{ needs.extract-version.outputs.is_push_to_main }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [[ "${{ needs.extract-version.outputs.is_push_to_main }}" == "true" ]]; then
|
||||
echo "### Published Tags:" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [[ "${{ needs.build-regular.result }}" == "success" ]]; then
|
||||
echo "✅ **Regular:** \`${{ env.GHCR_IMAGE }}:v1-dev\`" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then
|
||||
echo "✅ **Regular (Docker Hub):** \`${{ env.DOCKERHUB_IMAGE }}:v1-dev\`" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
else
|
||||
echo "❌ **Regular:** Build failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [[ "${{ needs.build-single.result }}" == "success" ]]; then
|
||||
echo "✅ **Single:** \`${{ env.GHCR_IMAGE }}:v1-dev-single\`" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then
|
||||
echo "✅ **Single (Docker Hub):** \`${{ env.DOCKERHUB_IMAGE }}:v1-dev-single\`" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
elif [[ "${{ needs.build-single.result }}" == "skipped" ]]; then
|
||||
echo "⏭️ **Single:** Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **Single:** Build failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Platforms:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- linux/amd64" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- linux/arm64" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "### Test Build Results:" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${{ needs.build-regular.result }}" == "success" ]]; then
|
||||
echo "✅ **Dockerfile:** Build successful" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **Dockerfile:** Build failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Notes:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- This is a test build (no images pushed to registry)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Merge to main to publish \`v1-dev\` tags" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- For stable releases, use the 'Build and Release' workflow" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
@@ -0,0 +1,16 @@
|
||||
name: Docs Link Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "**/*.md"
|
||||
- "scripts/check_md_links.py"
|
||||
- ".github/workflows/docs-links.yml"
|
||||
|
||||
jobs:
|
||||
check-links:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check relative markdown links
|
||||
run: python3 scripts/check_md_links.py
|
||||
@@ -0,0 +1,159 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
push:
|
||||
branches: [main]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'docs/**'
|
||||
- '.github/workflows/claude*.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
backend:
|
||||
name: Backend Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v8.1.0
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Set up Python
|
||||
run: uv python install
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: uv run pytest tests/ -v --cov=open_notebook --cov=api --cov-report=term-missing --cov-report=xml
|
||||
|
||||
- name: Upload coverage artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: backend-coverage
|
||||
path: coverage.xml
|
||||
|
||||
backend-lint:
|
||||
name: Backend Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v8.1.0
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Set up Python
|
||||
run: uv python install
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync
|
||||
|
||||
- name: Run ruff
|
||||
run: uv run ruff check .
|
||||
|
||||
backend-typecheck:
|
||||
name: Backend Typecheck
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v8.1.0
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Set up Python
|
||||
run: uv python install
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync
|
||||
|
||||
- name: Run mypy
|
||||
run: uv run python -m mypy .
|
||||
|
||||
frontend:
|
||||
name: Frontend Tests
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontend
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: npm run test:coverage
|
||||
|
||||
- name: Upload coverage artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: frontend-coverage
|
||||
path: frontend/coverage/
|
||||
|
||||
frontend-lint:
|
||||
name: Frontend Lint
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontend
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run ESLint
|
||||
run: npm run lint
|
||||
|
||||
frontend-build:
|
||||
name: Frontend Build
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontend
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
Reference in New Issue
Block a user