markkit 0.1.1__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.
- markkit-0.1.1/.agents/skills/process-issues/SKILL.md +52 -0
- markkit-0.1.1/.agents/skills/ship/SKILL.md +61 -0
- markkit-0.1.1/.claude/commands/maintain.md +49 -0
- markkit-0.1.1/.claude/hooks/fix-git-identity.sh +13 -0
- markkit-0.1.1/.claude/settings.json +20 -0
- markkit-0.1.1/.github/dependabot.yml +25 -0
- markkit-0.1.1/.github/workflows/ci.yml +80 -0
- markkit-0.1.1/.github/workflows/coverage.yml +25 -0
- markkit-0.1.1/.github/workflows/js.yml +38 -0
- markkit-0.1.1/.github/workflows/nightly.yml +21 -0
- markkit-0.1.1/.github/workflows/publish-js.yml +49 -0
- markkit-0.1.1/.github/workflows/publish-python.yml +128 -0
- markkit-0.1.1/.github/workflows/publish.yml +65 -0
- markkit-0.1.1/.github/workflows/python.yml +32 -0
- markkit-0.1.1/.github/workflows/release.yml +118 -0
- markkit-0.1.1/.gitignore +45 -0
- markkit-0.1.1/AGENTS.md +33 -0
- markkit-0.1.1/CHANGELOG.md +80 -0
- markkit-0.1.1/CLAUDE.md +1 -0
- markkit-0.1.1/CODE_OF_CONDUCT.md +44 -0
- markkit-0.1.1/CONTRIBUTING.md +62 -0
- markkit-0.1.1/Cargo.lock +3430 -0
- markkit-0.1.1/Cargo.toml +88 -0
- markkit-0.1.1/LICENSE +21 -0
- markkit-0.1.1/NOTICE +37 -0
- markkit-0.1.1/PKG-INFO +41 -0
- markkit-0.1.1/README.md +158 -0
- markkit-0.1.1/SECURITY.md +45 -0
- markkit-0.1.1/crates/markkit/Cargo.toml +100 -0
- markkit-0.1.1/crates/markkit/benches/extraction.rs +18 -0
- markkit-0.1.1/crates/markkit/src/archive.rs +173 -0
- markkit-0.1.1/crates/markkit/src/config.rs +134 -0
- markkit-0.1.1/crates/markkit/src/docx.rs +945 -0
- markkit-0.1.1/crates/markkit/src/error.rs +30 -0
- markkit-0.1.1/crates/markkit/src/extract.rs +292 -0
- markkit-0.1.1/crates/markkit/src/format.rs +265 -0
- markkit-0.1.1/crates/markkit/src/html/mod.rs +7 -0
- markkit-0.1.1/crates/markkit/src/html/parser.rs +517 -0
- markkit-0.1.1/crates/markkit/src/ir.rs +116 -0
- markkit-0.1.1/crates/markkit/src/lib.rs +68 -0
- markkit-0.1.1/crates/markkit/src/render/markdown.rs +402 -0
- markkit-0.1.1/crates/markkit/src/render/mod.rs +9 -0
- markkit-0.1.1/crates/markkit/src/spreadsheet.rs +716 -0
- markkit-0.1.1/crates/markkit/src/xml.rs +234 -0
- markkit-0.1.1/crates/markkit/tests/common/mod.rs +430 -0
- markkit-0.1.1/crates/markkit/tests/document_detection.rs +245 -0
- markkit-0.1.1/crates/markkit/tests/document_security.rs +405 -0
- markkit-0.1.1/crates/markkit/tests/docx_integration.rs +355 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/basic_headings.html +6 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/basic_headings.md +6 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/blockquotes.html +8 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/blockquotes.md +4 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/code_blocks.html +8 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/code_blocks.md +16 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/full_article.html +29 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/full_article.md +15 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/inline_formatting.html +6 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/inline_formatting.md +6 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/links_and_images.html +7 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/links_and_images.md +7 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/lists.html +23 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/lists.md +12 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/malformed.html +5 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/malformed.md +7 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/tables.html +25 -0
- markkit-0.1.1/crates/markkit/tests/fixtures/html/tables.md +14 -0
- markkit-0.1.1/crates/markkit/tests/html_fixtures.rs +66 -0
- markkit-0.1.1/crates/markkit/tests/html_integration.rs +695 -0
- markkit-0.1.1/crates/markkit/tests/html_proptest.proptest-regressions +7 -0
- markkit-0.1.1/crates/markkit/tests/html_proptest.rs +71 -0
- markkit-0.1.1/crates/markkit/tests/html_security.rs +206 -0
- markkit-0.1.1/crates/markkit/tests/spreadsheet_integration.rs +277 -0
- markkit-0.1.1/crates/markkit-bench/Cargo.toml +31 -0
- markkit-0.1.1/crates/markkit-bench/src/main.rs +21 -0
- markkit-0.1.1/crates/markkit-cli/Cargo.toml +37 -0
- markkit-0.1.1/crates/markkit-cli/src/main.rs +124 -0
- markkit-0.1.1/crates/markkit-cli/tests/cli_integration.rs +201 -0
- markkit-0.1.1/crates/markkit-eval/Cargo.toml +25 -0
- markkit-0.1.1/crates/markkit-eval/src/main.rs +22 -0
- markkit-0.1.1/crates/markkit-js/Cargo.toml +25 -0
- markkit-0.1.1/crates/markkit-js/README.md +17 -0
- markkit-0.1.1/crates/markkit-js/build.rs +5 -0
- markkit-0.1.1/crates/markkit-js/package.json +38 -0
- markkit-0.1.1/crates/markkit-js/src/lib.rs +39 -0
- markkit-0.1.1/crates/markkit-python/Cargo.toml +22 -0
- markkit-0.1.1/crates/markkit-python/README.md +29 -0
- markkit-0.1.1/crates/markkit-python/src/lib.rs +90 -0
- markkit-0.1.1/deny.toml +32 -0
- markkit-0.1.1/docs/getting-started.md +56 -0
- markkit-0.1.1/examples/basic.rs +27 -0
- markkit-0.1.1/examples/configuration.rs +37 -0
- markkit-0.1.1/examples/custom_selectors.rs +33 -0
- markkit-0.1.1/examples/ir_access.rs +47 -0
- markkit-0.1.1/justfile +111 -0
- markkit-0.1.1/pyproject.toml +16 -0
- markkit-0.1.1/rust-toolchain.toml +3 -0
- markkit-0.1.1/scripts/init-cloud-env.sh +90 -0
- markkit-0.1.1/scripts/lib/common.sh +60 -0
- markkit-0.1.1/specs/architecture.md +45 -0
- markkit-0.1.1/specs/documentation.md +26 -0
- markkit-0.1.1/specs/eval.md +25 -0
- markkit-0.1.1/specs/examples-spec.md +67 -0
- markkit-0.1.1/specs/format-support.md +108 -0
- markkit-0.1.1/specs/html-extraction.md +153 -0
- markkit-0.1.1/specs/ir-spec.md +132 -0
- markkit-0.1.1/specs/js-package.md +33 -0
- markkit-0.1.1/specs/maintenance.md +35 -0
- markkit-0.1.1/specs/python-package.md +34 -0
- markkit-0.1.1/specs/release-process.md +51 -0
- markkit-0.1.1/specs/security.md +38 -0
- markkit-0.1.1/specs/testing.md +43 -0
- markkit-0.1.1/specs/threat-model.md +242 -0
- markkit-0.1.1/supply-chain/config.toml +16 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Process open GitHub issues and resolve them via merged pull requests.
|
|
2
|
+
|
|
3
|
+
## Qualifying Issues
|
|
4
|
+
|
|
5
|
+
Only process issues created by authorized users or containing approval
|
|
6
|
+
comments from those users.
|
|
7
|
+
|
|
8
|
+
## Core Principle
|
|
9
|
+
|
|
10
|
+
One issue = one PR. No bundling. No skipping.
|
|
11
|
+
|
|
12
|
+
## Process Per Issue
|
|
13
|
+
|
|
14
|
+
### 1. Understand & Scope
|
|
15
|
+
- Read the issue thoroughly
|
|
16
|
+
- Classify: bug, feature, docs, refactor
|
|
17
|
+
- Identify affected crates and files
|
|
18
|
+
- Create branch: `fix/issue-{N}-{short-slug}`
|
|
19
|
+
|
|
20
|
+
### 2. Test First
|
|
21
|
+
- For bugs: create a failing test that reproduces the issue
|
|
22
|
+
- For features: scaffold validation tests
|
|
23
|
+
- Place tests alongside existing test modules
|
|
24
|
+
|
|
25
|
+
### 3. Implement
|
|
26
|
+
- Make minimal, focused changes
|
|
27
|
+
- Cover positive and negative test cases
|
|
28
|
+
- Consider security implications for parsing changes
|
|
29
|
+
|
|
30
|
+
### 4. Ship
|
|
31
|
+
- Use the `/ship` skill for:
|
|
32
|
+
- Spec updates
|
|
33
|
+
- Quality gates
|
|
34
|
+
- PR creation
|
|
35
|
+
- CI verification
|
|
36
|
+
- Merge
|
|
37
|
+
|
|
38
|
+
### 5. Return to Main
|
|
39
|
+
```bash
|
|
40
|
+
git checkout main && git pull origin main
|
|
41
|
+
```
|
|
42
|
+
Then proceed to next issue.
|
|
43
|
+
|
|
44
|
+
## Post-Resolution
|
|
45
|
+
|
|
46
|
+
After all issues are resolved, identify any `#[ignore]` tests
|
|
47
|
+
that now pass and un-ignore them in a single PR.
|
|
48
|
+
|
|
49
|
+
## Arguments
|
|
50
|
+
|
|
51
|
+
Optional: specific issue numbers or labels.
|
|
52
|
+
Default: process all qualifying open issues.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Run the full ship flow: verify quality, ensure test coverage, update
|
|
2
|
+
artifacts, smoke test, then push, create PR, address review comments,
|
|
3
|
+
and merge only when CI is green, all threads resolved, and user confirms.
|
|
4
|
+
|
|
5
|
+
## Phases
|
|
6
|
+
|
|
7
|
+
### 1. Pre-flight
|
|
8
|
+
- Verify on a feature branch (not main)
|
|
9
|
+
- Check for uncommitted changes
|
|
10
|
+
- Fetch latest main and rebase if needed
|
|
11
|
+
|
|
12
|
+
### 2. Test Coverage
|
|
13
|
+
- Identify changed code paths
|
|
14
|
+
- Ensure tests exist for:
|
|
15
|
+
- Positive cases (happy path)
|
|
16
|
+
- Negative cases (errors, edge cases)
|
|
17
|
+
- Security scenarios (malicious input)
|
|
18
|
+
- Add missing tests
|
|
19
|
+
|
|
20
|
+
### 3. Artifact Updates
|
|
21
|
+
- Update specs if behavior changed
|
|
22
|
+
- Update CHANGELOG.md for user-facing changes
|
|
23
|
+
- Update documentation for API changes
|
|
24
|
+
|
|
25
|
+
### 4. Simplification
|
|
26
|
+
- Remove dead code introduced by changes
|
|
27
|
+
- Reduce duplication
|
|
28
|
+
- Simplify where possible without changing behavior
|
|
29
|
+
|
|
30
|
+
### 5. Security Review
|
|
31
|
+
- Check for injection risks in new parsing code
|
|
32
|
+
- Verify resource limits are enforced
|
|
33
|
+
- Review input validation
|
|
34
|
+
|
|
35
|
+
### 6. Smoke Test
|
|
36
|
+
- Run `just test` for full test suite
|
|
37
|
+
- Run `just lint` for code quality
|
|
38
|
+
- Build CLI and verify basic extraction works
|
|
39
|
+
|
|
40
|
+
### 7. Quality Gates
|
|
41
|
+
- `cargo fmt --all -- --check`
|
|
42
|
+
- `cargo clippy --workspace -- -D warnings`
|
|
43
|
+
- `cargo deny check`
|
|
44
|
+
|
|
45
|
+
### 8. Push & PR
|
|
46
|
+
- Push branch to remote
|
|
47
|
+
- Create or update PR with summary
|
|
48
|
+
- Wait for CI to pass
|
|
49
|
+
|
|
50
|
+
### 9. Review & Merge
|
|
51
|
+
- Check for unresolved review comments — address or reply to each
|
|
52
|
+
- Ensure all review threads are resolved
|
|
53
|
+
- Confirm no changes-requested reviews remain outstanding
|
|
54
|
+
- Ask the user whether to merge now or wait for reviewer feedback
|
|
55
|
+
- Only merge when: CI green, no unresolved threads, no pending change requests
|
|
56
|
+
|
|
57
|
+
**IMPORTANT**: Phases 2-5 (tests, artifacts, simplification, security review,
|
|
58
|
+
smoke testing) are the quality core — do NOT skip them.
|
|
59
|
+
|
|
60
|
+
**IMPORTANT**: Never auto-merge without confirming with the user. PRs should
|
|
61
|
+
have time for human review before merging.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Run pre-release maintenance checks on the markkit codebase.
|
|
2
|
+
|
|
3
|
+
Each section below is an outcome to achieve, not a script to follow.
|
|
4
|
+
Use whatever tools and approaches make sense to verify and fix.
|
|
5
|
+
|
|
6
|
+
Fix issues as you find them — don't just report. Use conventional
|
|
7
|
+
commit messages for any fixes.
|
|
8
|
+
|
|
9
|
+
Sections (run all unless $ARGUMENTS specifies a subset):
|
|
10
|
+
|
|
11
|
+
## 1. Dependencies
|
|
12
|
+
- Run `cargo update` and verify tests pass
|
|
13
|
+
- Check for outdated dependencies
|
|
14
|
+
- Review Dependabot PRs if any
|
|
15
|
+
|
|
16
|
+
## 2. Security
|
|
17
|
+
- Run `cargo audit` for vulnerabilities
|
|
18
|
+
- Run `cargo deny check` for license compliance
|
|
19
|
+
- Review any new advisories
|
|
20
|
+
|
|
21
|
+
## 3. Tests
|
|
22
|
+
- Run full test suite: `just test`
|
|
23
|
+
- Check coverage isn't regressing
|
|
24
|
+
- Identify any `#[ignore]` tests that should be re-enabled
|
|
25
|
+
|
|
26
|
+
## 4. Documentation
|
|
27
|
+
- Verify README is current
|
|
28
|
+
- Check rustdoc builds without warnings
|
|
29
|
+
- Ensure specs match implementation
|
|
30
|
+
|
|
31
|
+
## 5. Examples
|
|
32
|
+
- Verify examples compile and run
|
|
33
|
+
- Update examples for any API changes
|
|
34
|
+
|
|
35
|
+
## 6. Specs
|
|
36
|
+
- Review specs/ for accuracy
|
|
37
|
+
- Update implementation status
|
|
38
|
+
|
|
39
|
+
## 7. Simplification
|
|
40
|
+
- Look for dead code, unused dependencies
|
|
41
|
+
- Identify duplication opportunities
|
|
42
|
+
- Reduce complexity where possible
|
|
43
|
+
|
|
44
|
+
## 8. CI Health
|
|
45
|
+
- Check recent GitHub Actions runs
|
|
46
|
+
- Verify nightly builds are passing
|
|
47
|
+
- Review any flaky tests
|
|
48
|
+
|
|
49
|
+
Deliver a summary of findings and actions taken.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SessionStart hook: override agent-like git identity with real user
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
git rev-parse --git-dir >/dev/null 2>&1 || exit 0
|
|
7
|
+
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
10
|
+
|
|
11
|
+
source "$REPO_ROOT/scripts/lib/common.sh"
|
|
12
|
+
|
|
13
|
+
configure_commit_git_identity_if_needed 2>/dev/null || true
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"gitAttribution": false,
|
|
3
|
+
"attribution": {
|
|
4
|
+
"commit": "",
|
|
5
|
+
"pr": ""
|
|
6
|
+
},
|
|
7
|
+
"hooks": {
|
|
8
|
+
"SessionStart": [
|
|
9
|
+
{
|
|
10
|
+
"matcher": "",
|
|
11
|
+
"hooks": [
|
|
12
|
+
{
|
|
13
|
+
"type": "command",
|
|
14
|
+
"command": ".claude/hooks/fix-git-identity.sh"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Rust dependencies
|
|
4
|
+
- package-ecosystem: "cargo"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
commit-message:
|
|
9
|
+
prefix: "chore(deps)"
|
|
10
|
+
groups:
|
|
11
|
+
rust-dependencies:
|
|
12
|
+
patterns:
|
|
13
|
+
- "*"
|
|
14
|
+
|
|
15
|
+
# GitHub Actions
|
|
16
|
+
- package-ecosystem: "github-actions"
|
|
17
|
+
directory: "/"
|
|
18
|
+
schedule:
|
|
19
|
+
interval: "weekly"
|
|
20
|
+
commit-message:
|
|
21
|
+
prefix: "chore(ci)"
|
|
22
|
+
groups:
|
|
23
|
+
github-actions:
|
|
24
|
+
patterns:
|
|
25
|
+
- "*"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
env:
|
|
11
|
+
CARGO_TERM_COLOR: always
|
|
12
|
+
RUSTFLAGS: -Dwarnings
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint:
|
|
16
|
+
name: Lint
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
21
|
+
with:
|
|
22
|
+
components: rustfmt, clippy
|
|
23
|
+
- uses: Swatinem/rust-cache@v2
|
|
24
|
+
- name: Check formatting
|
|
25
|
+
run: cargo fmt --all -- --check
|
|
26
|
+
- name: Clippy
|
|
27
|
+
run: cargo clippy --workspace --all-targets -- -D warnings
|
|
28
|
+
- name: Build docs
|
|
29
|
+
run: cargo doc --workspace --no-deps
|
|
30
|
+
env:
|
|
31
|
+
RUSTDOCFLAGS: -Dwarnings
|
|
32
|
+
|
|
33
|
+
audit:
|
|
34
|
+
name: Audit
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v4
|
|
38
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
39
|
+
- name: Install cargo-audit
|
|
40
|
+
run: cargo install cargo-audit
|
|
41
|
+
- name: Install cargo-deny
|
|
42
|
+
run: cargo install cargo-deny
|
|
43
|
+
- name: Security audit
|
|
44
|
+
run: cargo audit
|
|
45
|
+
- name: License and dependency check
|
|
46
|
+
run: cargo deny check
|
|
47
|
+
|
|
48
|
+
test:
|
|
49
|
+
name: Test
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
54
|
+
- uses: Swatinem/rust-cache@v2
|
|
55
|
+
- name: Run tests
|
|
56
|
+
run: cargo test --workspace
|
|
57
|
+
- name: Run tests (all features)
|
|
58
|
+
run: cargo test --workspace --all-features
|
|
59
|
+
- name: Run tests (office formats, no HTTP client)
|
|
60
|
+
run: |
|
|
61
|
+
cargo test -p markkit --no-default-features --features docx,spreadsheet
|
|
62
|
+
if cargo tree -p markkit --no-default-features --features docx,spreadsheet -e normal | grep -E 'reqwest|hyper'; then
|
|
63
|
+
echo "HTTP client leaked into the docx,spreadsheet feature set"
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
check:
|
|
68
|
+
name: Check
|
|
69
|
+
needs: [lint, audit, test]
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
if: always()
|
|
72
|
+
steps:
|
|
73
|
+
- name: All jobs passed
|
|
74
|
+
run: |
|
|
75
|
+
if [[ "${{ needs.lint.result }}" != "success" ]] || \
|
|
76
|
+
[[ "${{ needs.audit.result }}" != "success" ]] || \
|
|
77
|
+
[[ "${{ needs.test.result }}" != "success" ]]; then
|
|
78
|
+
echo "One or more jobs failed"
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Coverage
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
coverage:
|
|
11
|
+
name: Code Coverage
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
16
|
+
- uses: Swatinem/rust-cache@v2
|
|
17
|
+
- name: Install cargo-tarpaulin
|
|
18
|
+
run: cargo install cargo-tarpaulin
|
|
19
|
+
- name: Generate coverage
|
|
20
|
+
run: cargo tarpaulin --workspace --out xml
|
|
21
|
+
- name: Upload coverage
|
|
22
|
+
uses: codecov/codecov-action@v4
|
|
23
|
+
with:
|
|
24
|
+
file: cobertura.xml
|
|
25
|
+
fail_ci_if_error: false
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: JavaScript
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "crates/markkit-js/**"
|
|
8
|
+
- "crates/markkit/**"
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
paths:
|
|
12
|
+
- "crates/markkit-js/**"
|
|
13
|
+
- "crates/markkit/**"
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build:
|
|
17
|
+
name: Build Node.js bindings
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
22
|
+
- uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: "24.22.1"
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: cd crates/markkit-js && npm install --ignore-scripts --audit=false --fund=false
|
|
27
|
+
- name: Build
|
|
28
|
+
run: cd crates/markkit-js && npx --no-install napi build --release --platform
|
|
29
|
+
- name: Verify build preserved the patched lockfile
|
|
30
|
+
run: git diff --exit-code -- Cargo.lock
|
|
31
|
+
- name: Verify installed npm package
|
|
32
|
+
run: |
|
|
33
|
+
cd crates/markkit-js
|
|
34
|
+
npm pack --ignore-scripts --json > "$RUNNER_TEMP/markkit-pack.json"
|
|
35
|
+
node -e 'const p=require(process.argv[1])[0]; const files=p.files.map(f=>f.path); if(!files.includes("index.js") || !files.some(f=>f.endsWith(".node"))) throw Error("npm package must contain its loader and native binary")' "$RUNNER_TEMP/markkit-pack.json"
|
|
36
|
+
TARBALL=$(node -e 'console.log(require(process.argv[1])[0].filename)' "$RUNNER_TEMP/markkit-pack.json")
|
|
37
|
+
npm install --prefix "$RUNNER_TEMP/markkit-npm-smoke" --ignore-scripts --audit=false --fund=false "$PWD/$TARBALL"
|
|
38
|
+
node -e 'const m=require(process.argv[1]); if(m.extractHtmlSync("<h1>Smoke</h1>").trim()!=="# Smoke") throw Error("native extraction smoke failed")' "$RUNNER_TEMP/markkit-npm-smoke/node_modules/@everruns/markkit"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Nightly
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 4 * * *"
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
nightly:
|
|
10
|
+
name: Nightly checks
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: dtolnay/rust-toolchain@nightly
|
|
15
|
+
with:
|
|
16
|
+
components: rustfmt, clippy
|
|
17
|
+
- uses: Swatinem/rust-cache@v2
|
|
18
|
+
- name: Build on nightly
|
|
19
|
+
run: cargo build --workspace
|
|
20
|
+
- name: Test on nightly
|
|
21
|
+
run: cargo test --workspace
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Publish JavaScript
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
dry_run:
|
|
7
|
+
description: "Dry run"
|
|
8
|
+
required: false
|
|
9
|
+
default: "true"
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
name: Publish npm package
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
18
|
+
- uses: actions/setup-node@v4
|
|
19
|
+
with:
|
|
20
|
+
node-version: "24.22.1"
|
|
21
|
+
registry-url: "https://registry.npmjs.org"
|
|
22
|
+
- name: Require npm publisher credential
|
|
23
|
+
if: inputs.dry_run != 'true'
|
|
24
|
+
env:
|
|
25
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
26
|
+
run: |
|
|
27
|
+
if [ -z "$NODE_AUTH_TOKEN" ]; then
|
|
28
|
+
echo "::error::NPM_TOKEN is unavailable for this publisher"
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: cd crates/markkit-js && npm install --ignore-scripts --audit=false --fund=false
|
|
33
|
+
- name: Build
|
|
34
|
+
run: cd crates/markkit-js && npx --no-install napi build --release --platform
|
|
35
|
+
- name: Verify build preserved the patched lockfile
|
|
36
|
+
run: git diff --exit-code -- Cargo.lock
|
|
37
|
+
- name: Verify installed npm package
|
|
38
|
+
run: |
|
|
39
|
+
cd crates/markkit-js
|
|
40
|
+
npm pack --ignore-scripts --json > "$RUNNER_TEMP/markkit-pack.json"
|
|
41
|
+
node -e 'const p=require(process.argv[1])[0]; const files=p.files.map(f=>f.path); if(!files.includes("index.js") || !files.some(f=>f.endsWith(".node"))) throw Error("npm package must contain its loader and native binary")' "$RUNNER_TEMP/markkit-pack.json"
|
|
42
|
+
TARBALL=$(node -e 'console.log(require(process.argv[1])[0].filename)' "$RUNNER_TEMP/markkit-pack.json")
|
|
43
|
+
npm install --prefix "$RUNNER_TEMP/markkit-npm-smoke" --ignore-scripts --audit=false --fund=false "$PWD/$TARBALL"
|
|
44
|
+
node -e 'const m=require(process.argv[1]); if(m.extractHtmlSync("<h1>Smoke</h1>").trim()!=="# Smoke") throw Error("native extraction smoke failed")' "$RUNNER_TEMP/markkit-npm-smoke/node_modules/@everruns/markkit"
|
|
45
|
+
- name: Publish
|
|
46
|
+
if: inputs.dry_run != 'true'
|
|
47
|
+
run: cd crates/markkit-js && npm publish --ignore-scripts
|
|
48
|
+
env:
|
|
49
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
name: Publish Python
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
dry_run:
|
|
7
|
+
description: "Build and verify without publishing"
|
|
8
|
+
required: false
|
|
9
|
+
default: "true"
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: Build and verify Python distributions
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
outputs:
|
|
19
|
+
version: ${{ steps.metadata.outputs.version }}
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
23
|
+
- uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.12"
|
|
26
|
+
- name: Install packaging tools
|
|
27
|
+
run: python -m pip install maturin==1.15.0 twine==7.0.0
|
|
28
|
+
- name: Build from source distribution
|
|
29
|
+
run: maturin build --release --locked --sdist
|
|
30
|
+
- name: Verify build preserved the patched lockfile
|
|
31
|
+
run: git diff --exit-code -- Cargo.lock
|
|
32
|
+
- name: Inspect distribution identity
|
|
33
|
+
id: metadata
|
|
34
|
+
run: |
|
|
35
|
+
python <<'PYTHON'
|
|
36
|
+
import email.parser
|
|
37
|
+
import os
|
|
38
|
+
import pathlib
|
|
39
|
+
import zipfile
|
|
40
|
+
wheels = list(pathlib.Path("target/wheels").glob("*.whl"))
|
|
41
|
+
assert len(wheels) == 1
|
|
42
|
+
with zipfile.ZipFile(wheels[0]) as wheel:
|
|
43
|
+
metadata = email.parser.BytesParser().parsebytes(wheel.read(next(name for name in wheel.namelist() if name.endswith(".dist-info/METADATA"))))
|
|
44
|
+
assert metadata["Name"] == "markkit"
|
|
45
|
+
with open(os.environ["GITHUB_OUTPUT"], "a") as output:
|
|
46
|
+
print(f"version={metadata['Version']}", file=output)
|
|
47
|
+
print(f"markkit {metadata['Version']} from {os.environ['GITHUB_SHA']}")
|
|
48
|
+
PYTHON
|
|
49
|
+
- name: Verify distributions and native import
|
|
50
|
+
run: |
|
|
51
|
+
python -m twine check --strict target/wheels/*.whl target/wheels/*.tar.gz
|
|
52
|
+
python -m venv "$RUNNER_TEMP/markkit-wheel-smoke"
|
|
53
|
+
"$RUNNER_TEMP/markkit-wheel-smoke/bin/python" -m pip install --no-deps target/wheels/*.whl
|
|
54
|
+
"$RUNNER_TEMP/markkit-wheel-smoke/bin/python" -c 'import importlib.metadata, importlib.util, markkit; assert importlib.metadata.metadata("markkit")["Name"] == "markkit"; assert importlib.util.find_spec("markkit_python") is None; assert markkit.extract_html_sync("<h1>Smoke</h1>").strip() == "# Smoke"'
|
|
55
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
56
|
+
with:
|
|
57
|
+
name: python-distributions
|
|
58
|
+
path: |
|
|
59
|
+
target/wheels/*.whl
|
|
60
|
+
target/wheels/*.tar.gz
|
|
61
|
+
if-no-files-found: error
|
|
62
|
+
|
|
63
|
+
publish:
|
|
64
|
+
name: Publish Python package with OIDC
|
|
65
|
+
needs: build
|
|
66
|
+
if: inputs.dry_run != 'true'
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
permissions:
|
|
69
|
+
contents: read
|
|
70
|
+
id-token: write
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
73
|
+
with:
|
|
74
|
+
name: python-distributions
|
|
75
|
+
path: dist
|
|
76
|
+
- name: Publish to PyPI
|
|
77
|
+
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # release/v1
|
|
78
|
+
with:
|
|
79
|
+
packages-dir: dist/
|
|
80
|
+
|
|
81
|
+
verify:
|
|
82
|
+
name: Verify public PyPI installation
|
|
83
|
+
needs: [build, publish]
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
env:
|
|
86
|
+
MARKKIT_VERSION: ${{ needs.build.outputs.version }}
|
|
87
|
+
steps:
|
|
88
|
+
- uses: actions/setup-python@v5
|
|
89
|
+
with:
|
|
90
|
+
python-version: "3.12"
|
|
91
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
92
|
+
with:
|
|
93
|
+
name: python-distributions
|
|
94
|
+
path: dist
|
|
95
|
+
- name: Download the published wheel
|
|
96
|
+
run: |
|
|
97
|
+
for attempt in 1 2 3 4 5; do
|
|
98
|
+
if python -m pip download --no-cache-dir --only-binary=:all: --no-deps --dest registry "markkit==$MARKKIT_VERSION"; then
|
|
99
|
+
break
|
|
100
|
+
fi
|
|
101
|
+
if [ "$attempt" -eq 5 ]; then exit 1; fi
|
|
102
|
+
sleep 10
|
|
103
|
+
done
|
|
104
|
+
- name: Verify public files match the build
|
|
105
|
+
run: |
|
|
106
|
+
python <<'PYTHON'
|
|
107
|
+
import hashlib
|
|
108
|
+
import json
|
|
109
|
+
import os
|
|
110
|
+
import pathlib
|
|
111
|
+
import urllib.request
|
|
112
|
+
version = os.environ["MARKKIT_VERSION"]
|
|
113
|
+
with urllib.request.urlopen(f"https://pypi.org/pypi/markkit/{version}/json") as response:
|
|
114
|
+
published = json.load(response)
|
|
115
|
+
assert published["info"]["name"] == "markkit"
|
|
116
|
+
assert published["info"]["version"] == version
|
|
117
|
+
digests = {entry["filename"]: entry["digests"]["sha256"] for entry in published["urls"]}
|
|
118
|
+
for artifact in pathlib.Path("dist").iterdir():
|
|
119
|
+
assert digests[artifact.name] == hashlib.sha256(artifact.read_bytes()).hexdigest()
|
|
120
|
+
for wheel in pathlib.Path("registry").glob("*.whl"):
|
|
121
|
+
assert digests[wheel.name] == hashlib.sha256(wheel.read_bytes()).hexdigest()
|
|
122
|
+
print(f"Public markkit {version} distributions match the build")
|
|
123
|
+
PYTHON
|
|
124
|
+
- name: Install and smoke-test the public wheel
|
|
125
|
+
run: |
|
|
126
|
+
python -m venv "$RUNNER_TEMP/markkit-public-smoke"
|
|
127
|
+
"$RUNNER_TEMP/markkit-public-smoke/bin/python" -m pip install --no-index --no-deps registry/*.whl
|
|
128
|
+
"$RUNNER_TEMP/markkit-public-smoke/bin/python" -c 'import importlib.metadata, importlib.util, markkit; assert importlib.metadata.version("markkit") == __import__("os").environ["MARKKIT_VERSION"]; assert importlib.util.find_spec("markkit_python") is None; assert markkit.extract_html_sync("<h1>Published smoke</h1>").strip() == "# Published smoke"; print("Public markkit import and native extraction PASS")'
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
# Decisions:
|
|
4
|
+
# - Runs from a release tag (dispatched by release.yml, or manually from a tag).
|
|
5
|
+
# - Idempotent: a crate whose version is already on crates.io is skipped, so
|
|
6
|
+
# re-running a release never fails on an already-published crate.
|
|
7
|
+
# - Each crate is verified with a dry run before the credentialed upload.
|
|
8
|
+
on:
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
env:
|
|
15
|
+
CARGO_TERM_COLOR: always
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
publish:
|
|
19
|
+
name: Publish to crates.io
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
persist-credentials: false
|
|
25
|
+
|
|
26
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
27
|
+
|
|
28
|
+
- name: Verify tag and version
|
|
29
|
+
id: version
|
|
30
|
+
run: |
|
|
31
|
+
if [[ ! "$GITHUB_REF" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
32
|
+
echo "Error: publish must run from a release tag (vX.Y.Z), got $GITHUB_REF"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
|
|
36
|
+
CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
|
37
|
+
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
|
|
38
|
+
echo "Error: tag version ($TAG_VERSION) does not match Cargo.toml ($CARGO_VERSION)"
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
git fetch --no-tags origin main:refs/remotes/origin/main
|
|
42
|
+
if ! git merge-base --is-ancestor HEAD origin/main; then
|
|
43
|
+
echo "Error: publish source is not reachable from origin/main"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
echo "version=$CARGO_VERSION" >> "$GITHUB_OUTPUT"
|
|
47
|
+
|
|
48
|
+
- name: Publish crates
|
|
49
|
+
env:
|
|
50
|
+
VERSION: ${{ steps.version.outputs.version }}
|
|
51
|
+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
|
52
|
+
run: |
|
|
53
|
+
published() {
|
|
54
|
+
curl -sf -A "markkit-release (github.com/everruns/markkit)" \
|
|
55
|
+
"https://crates.io/api/v1/crates/$1/$VERSION" > /dev/null
|
|
56
|
+
}
|
|
57
|
+
# Dependency order: markkit-cli depends on markkit.
|
|
58
|
+
for crate in markkit markkit-cli; do
|
|
59
|
+
if published "$crate"; then
|
|
60
|
+
echo "$crate $VERSION already on crates.io; skipping"
|
|
61
|
+
continue
|
|
62
|
+
fi
|
|
63
|
+
cargo publish --dry-run -p "$crate"
|
|
64
|
+
cargo publish --no-verify -p "$crate"
|
|
65
|
+
done
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Python
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "crates/markkit-python/**"
|
|
8
|
+
- "crates/markkit/**"
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
paths:
|
|
12
|
+
- "crates/markkit-python/**"
|
|
13
|
+
- "crates/markkit/**"
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build:
|
|
17
|
+
name: Build Python bindings
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
- name: Install maturin
|
|
26
|
+
run: pip install maturin
|
|
27
|
+
- name: Build
|
|
28
|
+
run: maturin build
|
|
29
|
+
- name: Test import
|
|
30
|
+
run: |
|
|
31
|
+
pip install target/wheels/*.whl
|
|
32
|
+
python -c 'from importlib.metadata import metadata; import markkit; assert metadata("markkit")["Name"] == "markkit"; assert markkit.extract_html_sync("<h1>Smoke</h1>").strip() == "# Smoke"; print("Distribution and import OK")'
|