practicode 0.1.0 → 0.1.1
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.
- package/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/README.md +39 -100
- package/THIRD_PARTY_LICENSES.md +58 -0
- package/docs/CONTRIBUTING.md +76 -0
- package/package.json +4 -2
- package/scripts/release.sh +69 -0
- package/src/core.rs +271 -32
- package/src/tui.rs +363 -60
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -11,70 +11,55 @@
|
|
|
11
11
|
Personal coding practice, right in your terminal.
|
|
12
12
|
|
|
13
13
|
`practicode` is a small Rust TUI for stdin/stdout practice: problem on the left, code on the right, judge loop in the same terminal.
|
|
14
|
-
No browser tab shuffle, no paste dance, just solve and run.
|
|
15
14
|
|
|
16
|
-
##
|
|
15
|
+
## Start
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
- Gradual problem flow with local history
|
|
20
|
-
- AI-powered `/next <request>` when you want a custom problem
|
|
21
|
-
- Personal problem-generation notes
|
|
22
|
-
- Small stack: Rust, Ratatui, Crossterm, and plain process execution
|
|
17
|
+
### Prerequisites
|
|
23
18
|
|
|
24
|
-
|
|
19
|
+
- Node.js 18+ for npm installation.
|
|
20
|
+
- Rust and Cargo. The npm package builds the Rust binary during install, and also on first run if needed.
|
|
21
|
+
- A runtime for the language you practice in: Python, Node.js for TypeScript, JDK for Java, or Rust.
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
git clone https://github.com/baba9811/practicode.git
|
|
28
|
-
cd practicode
|
|
29
|
-
cargo run --
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Want a local binary?
|
|
23
|
+
### npm
|
|
33
24
|
|
|
34
25
|
```bash
|
|
35
|
-
|
|
26
|
+
npm install -g practicode
|
|
36
27
|
practicode
|
|
37
28
|
```
|
|
38
29
|
|
|
39
|
-
|
|
30
|
+
### Cargo
|
|
40
31
|
|
|
41
32
|
```bash
|
|
42
|
-
|
|
43
|
-
practicode
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Working from a local checkout?
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
cargo install --path .
|
|
33
|
+
cargo install practicode
|
|
50
34
|
practicode
|
|
51
35
|
```
|
|
52
36
|
|
|
53
|
-
|
|
37
|
+
### Local checkout
|
|
54
38
|
|
|
55
39
|
```bash
|
|
56
|
-
|
|
57
|
-
practicode
|
|
40
|
+
git clone https://github.com/baba9811/practicode.git
|
|
41
|
+
cd practicode
|
|
42
|
+
npm install
|
|
43
|
+
npm start
|
|
58
44
|
```
|
|
59
45
|
|
|
60
|
-
The npm wrapper builds the Rust binary with Cargo, so Rust/Cargo is still required.
|
|
61
|
-
|
|
62
46
|
## Daily Loop
|
|
63
47
|
|
|
64
48
|
The code editor starts focused.
|
|
65
49
|
|
|
66
50
|
```text
|
|
67
51
|
write code
|
|
68
|
-
Esc, then /
|
|
69
|
-
|
|
52
|
+
Esc, then /
|
|
53
|
+
choose /run
|
|
54
|
+
choose /next when it passes
|
|
70
55
|
```
|
|
71
56
|
|
|
57
|
+
Typing `/` outside the editor opens the command palette. Use `up/down` to move, `Enter` to run or complete the selected command, and `Esc` to cancel.
|
|
58
|
+
|
|
72
59
|
Submissions are saved as you type under `submissions/<problem-id>/solution.<ext>`.
|
|
73
60
|
|
|
74
61
|
## Commands
|
|
75
62
|
|
|
76
|
-
Press `Esc`, then `/`, to focus the command bar.
|
|
77
|
-
|
|
78
63
|
| Command | Action |
|
|
79
64
|
| --- | --- |
|
|
80
65
|
| `/run` | Judge the current submission |
|
|
@@ -86,21 +71,20 @@ Press `Esc`, then `/`, to focus the command bar.
|
|
|
86
71
|
| `/giveup` | Show the reference answer |
|
|
87
72
|
| `/ai hint` | Ask the selected AI about the current problem and submission |
|
|
88
73
|
| `/provider codex` | Set AI provider: `codex` or `claude` |
|
|
89
|
-
| `/model
|
|
74
|
+
| `/model auto` | Set the model for `/ai` and AI-backed `/next` |
|
|
90
75
|
| `/note prefer hashmap practice` | Append a standing note for future problem generation |
|
|
91
76
|
| `/notes` | Show your local next-problem notes |
|
|
92
|
-
| `/lang python` | Set language: `python`, `ts`, `java`, `rust` |
|
|
93
|
-
| `/ui
|
|
94
|
-
| `/theme` |
|
|
77
|
+
| `/lang python` | Set code language: `python`, `ts`, `java`, `rust` |
|
|
78
|
+
| `/ui en` | Set UI language: `en`, `ko`, `ja`, `zh`, `es` |
|
|
79
|
+
| `/theme dark` | Set theme: `dark` or `light` |
|
|
95
80
|
| `/source ai` | Prefer AI for next-problem generation |
|
|
96
81
|
| `/exit` | Quit |
|
|
97
82
|
|
|
98
|
-
The
|
|
99
|
-
Press `Esc`, then `/`, when you want the command bar.
|
|
83
|
+
The default UI language is English. Switch it any time with `/ui ko`, `/ui ja`, `/ui zh`, or `/ui es`.
|
|
100
84
|
|
|
101
|
-
##
|
|
85
|
+
## AI Problems
|
|
102
86
|
|
|
103
|
-
`/next <request>` passes your request into the selected AI problem generator.
|
|
87
|
+
`/next <request>` passes your request into the selected AI problem generator.
|
|
104
88
|
|
|
105
89
|
```text
|
|
106
90
|
/next a slightly harder string problem
|
|
@@ -108,19 +92,7 @@ Press `Esc`, then `/`, when you want the command bar.
|
|
|
108
92
|
/next sorting problem, no graph yet
|
|
109
93
|
```
|
|
110
94
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
```text
|
|
114
|
-
/note Prefer concise statements.
|
|
115
|
-
/note I want more string and hashmap practice.
|
|
116
|
-
/note Avoid DP until I ask for it.
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Those notes are stored in `.practicode/problem_notes.md`, so they stay local.
|
|
120
|
-
|
|
121
|
-
## AI Providers
|
|
122
|
-
|
|
123
|
-
Codex is the default:
|
|
95
|
+
Codex is the default provider:
|
|
124
96
|
|
|
125
97
|
```text
|
|
126
98
|
/provider codex
|
|
@@ -135,10 +107,7 @@ Claude Code is also supported:
|
|
|
135
107
|
/source ai
|
|
136
108
|
```
|
|
137
109
|
|
|
138
|
-
|
|
139
|
-
If you want a custom daemon or wrapper script, set `/ai-next-command <shell command>`; practicode passes `PRACTICODE_NEXT_REQUEST`, `PRACTICODE_AI_PROVIDER`, and `PRACTICODE_AI_MODEL`.
|
|
140
|
-
|
|
141
|
-
Generated problem banks stay local:
|
|
110
|
+
Generated problem banks and submissions stay local:
|
|
142
111
|
|
|
143
112
|
| Path | Purpose |
|
|
144
113
|
| --- | --- |
|
|
@@ -150,51 +119,21 @@ Generated problem banks stay local:
|
|
|
150
119
|
|
|
151
120
|
Those paths are ignored by git, so your practice history stays yours.
|
|
152
121
|
|
|
153
|
-
##
|
|
154
|
-
|
|
155
|
-
`/run` executes your local submission as a normal process. practicode runs it from `.practicode/build/<problem-id>/run`, but this is not an OS sandbox. Only run code you trust.
|
|
156
|
-
|
|
157
|
-
## Debug Prints
|
|
122
|
+
## Update
|
|
158
123
|
|
|
159
|
-
|
|
124
|
+
```bash
|
|
125
|
+
npm update -g practicode
|
|
126
|
+
cargo install --force practicode
|
|
127
|
+
```
|
|
160
128
|
|
|
161
|
-
|
|
162
|
-
import sys
|
|
129
|
+
## Safety
|
|
163
130
|
|
|
164
|
-
|
|
165
|
-
```
|
|
131
|
+
`/run` executes your local submission as a normal process. practicode runs it from `.practicode/build/<problem-id>/run`, but this is not an OS sandbox. Only run code you trust.
|
|
166
132
|
|
|
167
|
-
##
|
|
133
|
+
## Contributors
|
|
168
134
|
|
|
169
|
-
|
|
170
|
-
cargo test
|
|
171
|
-
cargo run -- --smoke
|
|
172
|
-
cargo run --
|
|
173
|
-
```
|
|
135
|
+
Development, release, problem-authoring, and design references live in [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md).
|
|
174
136
|
|
|
175
|
-
|
|
137
|
+
## License
|
|
176
138
|
|
|
177
|
-
|
|
178
|
-
| --- | --- |
|
|
179
|
-
| `src/core.rs` | Problem bank, state, rendering, judging |
|
|
180
|
-
| `src/tui.rs` | Ratatui app, editor, command parser |
|
|
181
|
-
| `src/ai.rs` | Codex/Claude command integration and notes |
|
|
182
|
-
| `src/text.rs` | UTF-8 cursor math and Hangul composition |
|
|
183
|
-
| `src/process.rs` | Process execution helpers |
|
|
184
|
-
| `tests/` | Integration tests split by module |
|
|
185
|
-
|
|
186
|
-
## Discovery Notes
|
|
187
|
-
|
|
188
|
-
Recommended GitHub topics for this repo:
|
|
189
|
-
`coding-practice`, `competitive-programming`, `algorithms`, `ratatui`, `tui`, `rust`, `codex`, `claude-code`, `local-first`.
|
|
190
|
-
|
|
191
|
-
## References
|
|
192
|
-
|
|
193
|
-
- Ratatui terminal UI library: https://ratatui.rs/
|
|
194
|
-
- Crossterm terminal backend/events: https://github.com/crossterm-rs/crossterm
|
|
195
|
-
- Codex CLI open-source repo: https://github.com/openai/codex
|
|
196
|
-
- Claude Code CLI reference: https://docs.anthropic.com/en/docs/claude-code/cli-reference
|
|
197
|
-
- Kattis problem package format: https://www.kattis.com/problem-package-format/
|
|
198
|
-
- ICPC judging guidelines: https://icpc.global/regionals/regional-contest-cookbook-judging-guidelines
|
|
199
|
-
- GitHub README image guidance: https://docs.github.com/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes
|
|
200
|
-
- GitHub repository topics: https://docs.github.com/articles/classifying-your-repository-with-topics
|
|
139
|
+
practicode is MIT licensed. Third-party dependency license notes are in [THIRD_PARTY_LICENSES.md](THIRD_PARTY_LICENSES.md).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Third-Party Licenses
|
|
2
|
+
|
|
3
|
+
This file summarizes third-party dependency license metadata for practicode
|
|
4
|
+
0.1.0, checked from Cargo.lock and Cargo metadata.
|
|
5
|
+
|
|
6
|
+
This is not legal advice.
|
|
7
|
+
|
|
8
|
+
## Project License
|
|
9
|
+
|
|
10
|
+
practicode is licensed under MIT. The current dependency set is compatible with
|
|
11
|
+
that choice: all Rust dependencies use permissive licenses, and the npm package
|
|
12
|
+
has no npm dependencies.
|
|
13
|
+
|
|
14
|
+
## npm Dependencies
|
|
15
|
+
|
|
16
|
+
None.
|
|
17
|
+
|
|
18
|
+
## Direct Rust Dependencies
|
|
19
|
+
|
|
20
|
+
| Crate | Version | License |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| anyhow | 1.0.103 | MIT OR Apache-2.0 |
|
|
23
|
+
| crossterm | 0.29.0 | MIT |
|
|
24
|
+
| ratatui | 0.29.0 | MIT |
|
|
25
|
+
| serde | 1.0.228 | MIT OR Apache-2.0 |
|
|
26
|
+
| serde_json | 1.0.150 | MIT OR Apache-2.0 |
|
|
27
|
+
| unicode-width | 0.2.0 | MIT OR Apache-2.0 |
|
|
28
|
+
| wait-timeout | 0.2.1 | MIT/Apache-2.0 |
|
|
29
|
+
|
|
30
|
+
## Transitive Rust Dependency License Groups
|
|
31
|
+
|
|
32
|
+
The locked Rust dependency graph contains 87 third-party packages.
|
|
33
|
+
|
|
34
|
+
| License expression | Packages |
|
|
35
|
+
| --- | ---: |
|
|
36
|
+
| MIT OR Apache-2.0 | 50 |
|
|
37
|
+
| MIT | 20 |
|
|
38
|
+
| MIT/Apache-2.0 | 5 |
|
|
39
|
+
| Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | 5 |
|
|
40
|
+
| Apache-2.0 OR MIT | 1 |
|
|
41
|
+
| Apache-2.0/MIT | 1 |
|
|
42
|
+
| MIT / Apache-2.0 | 1 |
|
|
43
|
+
| Unlicense OR MIT | 1 |
|
|
44
|
+
| Zlib | 1 |
|
|
45
|
+
| Apache-2.0 OR BSL-1.0 | 1 |
|
|
46
|
+
| (MIT OR Apache-2.0) AND Unicode-3.0 | 1 |
|
|
47
|
+
|
|
48
|
+
No GPL, LGPL, AGPL, or MPL dependencies were detected in the locked Rust
|
|
49
|
+
dependency graph.
|
|
50
|
+
|
|
51
|
+
## Release Notes
|
|
52
|
+
|
|
53
|
+
The crates.io and npm packages distribute practicode source, not vendored
|
|
54
|
+
third-party source or prebuilt third-party binaries. The npm installer builds
|
|
55
|
+
the Rust binary locally with Cargo.
|
|
56
|
+
|
|
57
|
+
If practicode later ships prebuilt binaries, include full third-party notices
|
|
58
|
+
and license texts with those binary artifacts.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
This repo is a Rust coding-practice workspace with a Ratatui terminal UI.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Rust stable with Cargo, rustfmt, and clippy.
|
|
8
|
+
- Node.js 18+ for the npm wrapper and package checks.
|
|
9
|
+
- Optional local runtimes for judging: Python, Node.js, JDK, and Rust.
|
|
10
|
+
|
|
11
|
+
## Development
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cargo run --
|
|
15
|
+
cargo run -- --smoke
|
|
16
|
+
cargo test
|
|
17
|
+
npm run smoke
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Full local check:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
make test
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The source is split by boring responsibility:
|
|
27
|
+
|
|
28
|
+
| Path | Role |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| `src/core.rs` | Problem bank, state, rendering, judging |
|
|
31
|
+
| `src/tui.rs` | Ratatui app, editor, command parser |
|
|
32
|
+
| `src/ai.rs` | Codex/Claude command integration and notes |
|
|
33
|
+
| `src/text.rs` | UTF-8 cursor math and Hangul composition |
|
|
34
|
+
| `src/process.rs` | Process execution helpers |
|
|
35
|
+
| `tests/` | Integration tests split by module |
|
|
36
|
+
|
|
37
|
+
## Problem Authoring
|
|
38
|
+
|
|
39
|
+
AI generation reads [problem-authoring-notes.md](problem-authoring-notes.md) every time it creates a problem.
|
|
40
|
+
|
|
41
|
+
Local generated data stays ignored by git:
|
|
42
|
+
|
|
43
|
+
| Path | Purpose |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `.practicode/problem_bank.json` | Local/custom/generated problem bank |
|
|
46
|
+
| `.practicode/problem_notes.md` | Personal problem-generation notes |
|
|
47
|
+
| `.practicode/problem-state.json` | Current problem, history, settings |
|
|
48
|
+
| `problems/` | Generated problem markdown/index files |
|
|
49
|
+
| `submissions/` | Local answer files |
|
|
50
|
+
|
|
51
|
+
## Release
|
|
52
|
+
|
|
53
|
+
`main` runs CI only. Releases are tag-based and publish to crates.io and npm through GitHub Actions.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
make release VERSION=0.1.1
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The release script checks versions, runs tests, creates the version commit and tag, and pushes `main` plus the tag. Do not print or commit tokens; GitHub Actions uses repository secrets.
|
|
60
|
+
|
|
61
|
+
## Documentation
|
|
62
|
+
|
|
63
|
+
Keep the root [README](../README.md) focused on users. Put contributor workflow, implementation notes, release notes, and design references here or in nearby `docs/` files.
|
|
64
|
+
|
|
65
|
+
Use relative links for repo-local docs and assets. The terminal screenshot is stored at [assets/practicode-terminal.svg](../assets/practicode-terminal.svg).
|
|
66
|
+
|
|
67
|
+
## UX And Documentation References
|
|
68
|
+
|
|
69
|
+
- WAI-ARIA combobox keyboard interaction: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/
|
|
70
|
+
- Command Line Interface Guidelines: https://clig.dev/
|
|
71
|
+
- GitHub README guidance: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes
|
|
72
|
+
- GitHub relative links and images: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#relative-links
|
|
73
|
+
- Ratatui terminal UI library: https://ratatui.rs/
|
|
74
|
+
- Crossterm terminal backend/events: https://github.com/crossterm-rs/crossterm
|
|
75
|
+
- Kattis problem package format: https://www.kattis.com/problem-package-format/
|
|
76
|
+
- ICPC judging guidelines: https://icpc.global/regionals/regional-contest-cookbook-judging-guidelines
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "practicode",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Local-first coding-test practice in a Rust terminal UI with optional AI help.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"practicode": "bin/practicode.js"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
+
"start": "node bin/practicode.js",
|
|
15
16
|
"build": "cargo build --release --locked",
|
|
16
17
|
"postinstall": "node scripts/npm-postinstall.js",
|
|
17
18
|
"smoke": "node bin/practicode.js --smoke"
|
|
@@ -25,7 +26,8 @@
|
|
|
25
26
|
"Cargo.lock",
|
|
26
27
|
"Cargo.toml",
|
|
27
28
|
"LICENSE",
|
|
28
|
-
"README.md"
|
|
29
|
+
"README.md",
|
|
30
|
+
"THIRD_PARTY_LICENSES.md"
|
|
29
31
|
],
|
|
30
32
|
"keywords": [
|
|
31
33
|
"algorithms",
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
current=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)
|
|
5
|
+
npm_current=$(node -p "require('./package.json').version")
|
|
6
|
+
|
|
7
|
+
if [[ "$current" != "$npm_current" ]]; then
|
|
8
|
+
echo "Cargo.toml version ($current) does not match package.json ($npm_current)" >&2
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
if [[ -n "$(git status --porcelain)" ]]; then
|
|
13
|
+
echo "working tree is dirty; commit or stash changes first" >&2
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
branch=$(git branch --show-current)
|
|
18
|
+
if [[ "$branch" != "main" ]]; then
|
|
19
|
+
echo "release from main, not $branch" >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
git fetch origin main --tags
|
|
24
|
+
if [[ "$(git rev-parse HEAD)" != "$(git rev-parse origin/main)" ]]; then
|
|
25
|
+
echo "local main is not synced with origin/main" >&2
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
echo "Current version: $current"
|
|
30
|
+
version="${1:-}"
|
|
31
|
+
if [[ -z "$version" ]]; then
|
|
32
|
+
read -r -p "Next version: " version
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
36
|
+
echo "version must look like 0.1.1" >&2
|
|
37
|
+
exit 2
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
node -e '
|
|
41
|
+
const [current, next] = process.argv.slice(1).map(v => v.split(".").map(Number));
|
|
42
|
+
const ok = next[0] > current[0] ||
|
|
43
|
+
(next[0] === current[0] && (next[1] > current[1] ||
|
|
44
|
+
(next[1] === current[1] && next[2] > current[2])));
|
|
45
|
+
process.exit(ok ? 0 : 1);
|
|
46
|
+
' "$current" "$version" || {
|
|
47
|
+
echo "next version must be greater than $current" >&2
|
|
48
|
+
exit 2
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if git rev-parse -q --verify "refs/tags/v$version" >/dev/null; then
|
|
52
|
+
echo "tag v$version already exists locally" >&2
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
if git ls-remote --exit-code --tags origin "v$version" >/dev/null 2>&1; then
|
|
56
|
+
echo "tag v$version already exists on origin" >&2
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
echo "Releasing v$version"
|
|
61
|
+
VERSION="$version" perl -0pi -e 's/^version = ".*"/version = "$ENV{VERSION}"/m' Cargo.toml
|
|
62
|
+
node -e "const fs=require('fs'); const p=require('./package.json'); p.version=process.env.VERSION; fs.writeFileSync('package.json', JSON.stringify(p, null, 2) + '\n')"
|
|
63
|
+
cargo test
|
|
64
|
+
npm pack --dry-run >/dev/null
|
|
65
|
+
|
|
66
|
+
git add Cargo.toml Cargo.lock package.json
|
|
67
|
+
git commit -m "Release v$version"
|
|
68
|
+
git tag "v$version"
|
|
69
|
+
git push origin main "v$version"
|