Compare commits

...

13 Commits

Author SHA1 Message Date
3fb120f8a4 add web extension to release
Some checks failed
Release binary and debian package for cl-cli / webext-build (push) Successful in 32s
Release binary and debian package for cl-cli / build-and-release (push) Failing after 1m49s
2025-11-12 19:11:09 +01:00
f524dbfea8 add web extension to release
Some checks failed
Release binary and debian package for cl-cli / webext-build (push) Successful in 30s
Release binary and debian package for cl-cli / build-and-release (push) Failing after 1m49s
2025-11-12 19:03:09 +01:00
42796684d7 add web extension to release
Some checks failed
Release binary and debian package for cl-cli / webext-build (push) Failing after 49s
Release binary and debian package for cl-cli / build-and-release (push) Has been skipped
2025-11-12 18:55:27 +01:00
2871530da2 script to sign web extension 2025-11-12 18:36:18 +01:00
f30d299071 fix build and release
Some checks failed
Release binary and debian package for cl-cli / build-and-release (push) Failing after 1m53s
2025-11-12 09:09:49 +01:00
028a803447 fix build and release
Some checks failed
Release binary and debian package for cl-cli / build-and-release (push) Failing after 1m47s
2025-11-12 08:56:40 +01:00
d3c611974f fix build and release
Some checks failed
Release binary and debian package for cl-cli / build-and-release (push) Failing after 1m49s
2025-11-11 23:04:31 +01:00
b8577b4bac fix build and release
Some checks failed
Release binary and debian package for cl-cli / build-and-release (push) Failing after 1m49s
2025-11-11 22:57:08 +01:00
b705e34086 fix build and release
Some checks failed
Release binary and debian package for cl-cli / build-and-release (push) Failing after 1m46s
2025-11-11 22:51:19 +01:00
ad4e58926e Update release workflow to include Debian package build and upload
Some checks failed
Check go code / build-and-release (push) Successful in 1m7s
Release binary and debian package for cl-cli / build-and-release (push) Failing after 1m49s
Check go code / build-and-release (pull_request) Successful in 1m8s
Check go code / build-and-release (pull_request_target) Successful in 1m5s
2025-11-11 22:44:45 +01:00
056c885e8b Append metadata to build debian package using cargo-deb 2025-11-11 22:12:02 +01:00
b0f2a1452c configure changie to update the version number automatically into Cargo.toml 2025-11-11 22:11:15 +01:00
af8983ecdd Add junie guidelines 2025-11-11 00:54:34 +01:00
8 changed files with 219 additions and 13 deletions

View File

@@ -24,3 +24,9 @@ newlines:
beforeChangelogVersion: 1
endOfVersion: 1
envPrefix: CHANGIE_
# update the version in the cargo file, on release
replacements:
- path: Cargo.toml
find: '^version = ".*"'
replace: 'version = "{{.VersionNoPrefix}}"'

View File

@@ -1,4 +1,4 @@
name: Release binary for cl-cli
name: Release binary and debian package for cl-cli
on:
push:
@@ -6,28 +6,79 @@ on:
- v**
jobs:
webext-build:
runs-on: ubuntu-latest
container:
image: node:24
steps:
- name: Checkout repository
uses: https://github.com/actions/checkout@v4
- name: Install dependencies
run: cd web-extension/cl && npm install
- name: Build and sign web extension
env:
AMO_API_KEY: ${{ secrets.AMO_API_KEY }}
AMO_API_SECRET: ${{ secrets.AMO_API_SECRET }}
run: cd web-extension/cl && npm run sign
- name: Upload web extension artifact
uses: https://github.com/actions/upload-artifact@v3
with:
name: webext-xpi
path: web-extension/cl/web-ext-artifacts/*.xpi
retention-days: 7
if-no-files-found: error
build-and-release:
runs-on: ubuntu-latest
needs: [webext-build]
steps:
- name: Checkout repository
uses: https://github.com/actions/checkout@v4
- name: Install rust toolchain
uses: https://github.com/dtolnay/rust-toolchain@stable
- name: Build binaries
run: cargo build --release
- name: Read release content
uses: https://github.com/jaywcjlove/github-action-read-file@main
id: read_release
- name: Install cargo-deb
run: cargo install --quiet cargo-deb
- name: Build Debian package
run: cargo deb --quiet
- name: Upload Debian package to Gitea registry
env:
GITEA_OWNER: ${{ vars.PUBLISH_USERNAME }}
GITEA_SERVER_URL: ${{ github.server_url }}
GITEA_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
DEB_DISTRIBUTIONS: noble,plucky,questing
DEB_COMPONENT: main
DEB_ARCH: amd64
run: |
set -euo pipefail
DEB_FILE=$(ls target/debian/*.deb | head -n1)
if [ -z "${DEB_FILE}" ]; then
echo "No .deb file found in target/debian" >&2
exit 1
fi
# comma-separated in DEB_DISTRIBUTIONS, e.g. "noble,plucky,questing"
IFS=',' read -r -a DISTROS <<< "$DEB_DISTRIBUTIONS"
for DISTRO in "${DISTROS[@]}"; do
echo "Uploading ${DEB_FILE} to ${GITEA_SERVER_URL} for owner ${GITEA_OWNER}"
curl -sSf -X PUT \
--user "${GITEA_OWNER}:${GITEA_TOKEN}" \
--upload-file "${DEB_FILE}" \
"${GITEA_SERVER_URL}/api/packages/${GITEA_OWNER}/debian/pool/${DISTRO}/main/upload"
done
- name: Download web extension artifact
uses: https://github.com/actions/download-artifact@v3
with:
path: .changes/${{ github.ref_name }}.md
name: webext-xpi
path: web-extension/cl/web-ext-artifacts
- name: Release
uses: https://gitea.com/akkuman/gitea-release-action@v1
env:
NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18
with:
files: |-
target/release/cl-cli
config.toml.dist
web-extension/cl/web-ext-artifacts/*.xpi
md5sum: true
sha256sum: true
body_path: .changes/${{ github.ref_name }}.md
body: Test release
prerelease: true
#body_path: .changes/${{ github.ref_name }}.md

130
.junie/guidelines.md Normal file
View File

@@ -0,0 +1,130 @@
# cl-cli — Project-specific development guidelines
This document captures project-specific knowledge to help advanced contributors work efficiently on this repository. It focuses on practical, non-obvious details (build, configuration, testing, and development tips) specific to this codebase.
## 1. Build and configuration
- Rust workspace/binaries
- Single crate with two binaries defined in `Cargo.toml`:
- `cl-cli``src/main.rs`: the CLI entrypoint.
- `webext``src/webext.rs`: a Native Messaging host used by the browser extension.
- Library module tree under `src/lib.rs` exposes common code to both binaries.
- Toolchain: stable Rust; CI uses dtolnay/rust-toolchain@stable.
- Dependencies and async runtime
- Async via `tokio` (features: `rt`, `rt-multi-thread`, `macros`). Both binaries use `#[tokio::main]`.
- HTTP via `reqwest`; serialization via `serde`/`serde_json`; configuration via `toml`.
- Build
- Standard build works without extra flags:
- `cargo build` (debug) or `cargo build --release` (optimized).
- Individual binaries:
- `cargo build --bin cl-cli`
- `cargo build --bin webext`
- The web extension host (`webext`) is a regular Rust binary; it is not bundled by NPM tooling.
- Configuration file
- Expected location by default: `$HOME/.config/cl-cli/config.toml`.
- The CLI allows overriding the path via `--config <PATH>`; the webext host always reads the default path.
- Template: `config.toml.dist`. Minimal fields:
- `[[gitlab]] { token, domain }`
- `[[gitea]] { token, domain }`
- `[openproject] { token, base_url }`
- Example of initial setup (copy the dist and edit):
```bash
mkdir -p "$HOME/.config/cl-cli"
cp config.toml.dist "$HOME/.config/cl-cli/config.toml"
$EDITOR "$HOME/.config/cl-cli/config.toml"
```
- Error surface: parsing and IO errors are surfaced as `GeneralError`; the CLI will print and exit nonzero, the `webext` host will return an error payload.
- Local OpenProject for development
- `docker-compose.yaml` provides a local OpenProject (13.x) at `http://localhost:8080` with persisted volumes under `.docker-data/`.
## 2. Testing
- Test types present
- Unit tests live alongside code under `#[cfg(test)]` modules (e.g., `src/gitea/issue.rs`, `src/webext.rs`, `src/planning/utils.rs`).
- Integration tests can be placed under `tests/`. The crate exposes internal modules via `src/lib.rs` for integration testing.
- Running tests
- `cargo test` runs unit and integration tests. CI also runs `cargo test` on every push/PR.
- Tests are pure and do not require network or external services; avoid adding networkbound tests.
- Adding new tests
- Prefer unit tests near the logic being tested. For integration coverage across modules, place files under `tests/` and use public items from `cl_cli`.
- Keep tests deterministic: no real HTTP calls; if needed, mock boundaries at the client layer.
- Example integration test (verified locally during preparation)
- Minimal example using a pure helper. Create `tests/example_gitea_url.rs`:
```rust
use url::Url;
#[test]
fn converts_gitea_issue_html_url_to_api_url() {
// Pure transformation; no network
let input = Url::parse("https://gitea.champs-libres.be/champs-libres/test/issues/1").unwrap();
let out = cl_cli::gitea::issue::issue_html_url_to_api(&input).unwrap();
assert_eq!(
out.as_str(),
"https://gitea.champs-libres.be/api/v1/repos/champs-libres/test/issues/1"
);
}
```
- Run it with `cargo test`. Remove the file if it was only created as a demo.
## 3. CLI usage tips (projectspecific)
- `cl-cli planning i2work <gitlab_issue_url> <openproject_project_identifier>` creates an OpenProject work package from a GitLab issue.
- The OpenProject project identifier is the short slug in URLs, e.g. `chill` in `.../projects/chill/...`.
- The command uses tokens from the configuration file to authenticate to GitLab and OpenProject.
- Example:
```bash
cl-cli planning i2work \
https://gitlab.com/Chill-Projet/chill-bundles/-/issues/240 \
chill
```
- `cl-cli test` invokes a debug routine (see `src/debug.rs`) primarily for local diagnostics.
## 4. Web extension native host (`webext`)
- Purpose: acts as a Native Messaging host for a browser extension under `web-extension/`.
- Protocol: communicates via stdin/stdout using 4byte lengthprefixed JSON messages.
- Input `serde` enum is tagged with `type`; currently supports `{"type":"Issue2Work", ...}`.
- Output is tagged with `result` (`Ok` or `Error`) and contains `data` when successful.
- Business flow: the host reads config from `$HOME/.config/cl-cli/config.toml`, translates the input into `Issue2Work` CLI arguments, delegates to `planning::issue2work::handle_issue2work`, and returns the created work package URL.
- Testing the transport: see unit tests in `src/webext.rs` that exercise message framing and deserialization.
## 5. Code style and architectural notes
- Module layout
- Public library facade (`src/lib.rs`) reexports internal modules for reuse by both binaries and tests.
- Planning features under `src/planning/` with a trait (`Issue2WorkActionTrait`) and concrete actions per platform.
- Git providers (`src/gitlab`, `src/gitea`) and OpenProject client live in dedicated modules.
- Error handling
- Unified lightweight `GeneralError` encapsulates userfacing messages; conversions from `reqwest::Error` and header errors are provided.
- Data parsing
- Input/Output types rely on `serde` with explicit tagging for clarity and forward compatibility.
- Concurrency
- All async entrypoints are `#[tokio::main]`; downstream async functions return `impl Future` to stay generic and testable.
- External calls
- Wrap external service interactions behind client modules; this eases mocking in tests and keeps pure helpers (like URL mappers) easily testable.
## 6. Continuous Integration
- `.gitea/workflows/release/check.yaml` performs:
- Checkout → install stable toolchain → `cargo build` → `cargo test`.
- Release job (see `.gitea/workflows/release/build-and-release.yaml`) builds release artifacts for distribution.
## 7. Troubleshooting / gotchas (projectspecific)
- Config path
- The CLI accepts `--config`, but the webext host reads the default path only. Ensure `$HOME/.config/cl-cli/config.toml` exists when using the browser integration.
- Tokens scope
- Ensure personal access tokens for GitLab and OpenProject have sufficient scopes for reading issues and creating work packages respectively.
- Locale/URLs
- `Issue2Work` requires the OpenProject project identifier (slug), not its display name.
- HTTP environment
- `reqwest` honors proxy vars (`HTTP_PROXY`, `HTTPS_PROXY`) if present; be aware for corporate environments.
## 8. Commands quick reference
- Build: `cargo build --release`
- Run CLI: `cargo run --bin cl-cli -- <args>`
- Run webext host directly for dev: `cargo run --bin webext`
- Tests: `cargo test`
- Linting: `cargo clippy` (not enforced in CI but recommended)

2
Cargo.lock generated
View File

@@ -174,7 +174,7 @@ dependencies = [
[[package]]
name = "cl-cli"
version = "0.1.0"
version = "0.4.1-alpha9"
dependencies = [
"clap",
"gitlab",

View File

@@ -1,6 +1,6 @@
[package]
name = "cl-cli"
version = "0.1.0"
version = "0.4.1-alpha9"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -25,3 +25,15 @@ simple-home-dir = "0.5.2"
log = "0.4.28"
open = "5.3.2"
serde_json = "1.0.145"
[package.metadata.deb]
maintainer = "Julien Fastré <julien.fastre@champs-libres.coop>"
copyright = "AGPLv3"
extended-description = """Helpers for Champs-Libres"""
depends = "$auto"
section = "utility"
priority = "optional"
assets = [
["target/release/cl-cli", "usr/bin/cl", "755"],
["target/release/webext", "usr/bin/", "755"],
]

View File

@@ -0,0 +1,3 @@
# This file was created by https://github.com/mozilla/web-ext
# Your auto-generated extension ID for addons.mozilla.org is:
helper@champs-libres-coop

View File

@@ -5,7 +5,10 @@
"browser_specific_settings": {
"gecko": {
"id": "helper@champs-libres-coop",
"strict_min_version": "143.0"
"strict_min_version": "143.0",
"data_collection_permissions": {
"required": ["none"]
}
}
},

View File

@@ -7,7 +7,8 @@
"test": "echo \"Error: no test specified\" && exit 1",
"check": "tsc --noEmit",
"build": "tsc",
"package": "tsc && web-ext build --overwrite-dest"
"package": "tsc && web-ext build --overwrite-dest",
"sign": "tsc && web-ext build --overwrite-dest && web-ext sign --use-submission-api --api-key $AMO_API_KEY --api-secret $AMO_API_SECRET --channel unlisted"
},
"keywords": [],
"author": "",