studylife-cli 1.9.2__tar.gz → 1.9.4__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.
Files changed (37) hide show
  1. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/.github/workflows/ci.yml +61 -27
  2. studylife_cli-1.9.4/.github/workflows/dependabot-auto-merge.yml +22 -0
  3. studylife_cli-1.9.4/.github/workflows/dependabot-lockfiles.yml +20 -0
  4. studylife_cli-1.9.4/.github/workflows/dependency-review.yml +27 -0
  5. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/.github/workflows/scorecard.yml +2 -1
  6. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/CHANGELOG.md +14 -0
  7. studylife_cli-1.9.4/CODE_OF_CONDUCT.md +138 -0
  8. studylife_cli-1.9.4/CONTRIBUTING.md +65 -0
  9. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/PKG-INFO +1 -1
  10. studylife_cli-1.9.4/socket.yml +8 -0
  11. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/src/studylife_cli/_version.py +2 -2
  12. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/uv.lock +1 -1
  13. studylife_cli-1.9.2/.github/workflows/dependabot-auto-merge.yml +0 -77
  14. studylife_cli-1.9.2/.github/workflows/dependabot-lockfiles.yml +0 -80
  15. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  16. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  17. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  18. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  19. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/.github/dependabot.yml +0 -0
  20. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/.gitignore +0 -0
  21. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/.releaserc.json +0 -0
  22. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/LICENSE +0 -0
  23. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/README.md +0 -0
  24. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/SECURITY.md +0 -0
  25. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/fuzz/fuzz_models_and_callback.py +0 -0
  26. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/pyproject.toml +0 -0
  27. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/src/studylife_cli/__init__.py +0 -0
  28. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/src/studylife_cli/cli.py +0 -0
  29. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/src/studylife_cli/client.py +0 -0
  30. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/src/studylife_cli/credentials.py +0 -0
  31. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/src/studylife_cli/login.py +0 -0
  32. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/src/studylife_cli/models.py +0 -0
  33. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/src/studylife_cli/tui.py +0 -0
  34. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/tests/test_cli.py +0 -0
  35. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/tests/test_client.py +0 -0
  36. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/tests/test_login.py +0 -0
  37. {studylife_cli-1.9.2 → studylife_cli-1.9.4}/tests/test_tui.py +0 -0
@@ -10,6 +10,14 @@ concurrency:
10
10
  group: ci-${{ github.event.pull_request.number || github.ref }}
11
11
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}
12
12
 
13
+ env:
14
+ # uv must never download an interpreter from python-build-standalone: that is an
15
+ # external fetch on every single run (it started returning 504 Gateway Timeout on
16
+ # 2026-09-14 and turned CI red at random). The runner's tool cache already ships the
17
+ # version below, resolved locally by actions/setup-python - and with downloads off a
18
+ # missing interpreter fails loudly instead of being pulled in over the network.
19
+ UV_PYTHON_DOWNLOADS: never
20
+
13
21
  # Least-privilege default for GITHUB_TOKEN (CodeQL actions/missing-workflow-permissions):
14
22
  # jobs that need more declare it themselves.
15
23
  permissions:
@@ -18,26 +26,40 @@ permissions:
18
26
  jobs:
19
27
  lint:
20
28
  runs-on: ubuntu-latest
29
+ timeout-minutes: 15
21
30
  steps:
31
+ - name: Harden Runner
32
+ uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
33
+ with:
34
+ egress-policy: audit
22
35
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
23
- - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
36
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
24
37
  with:
25
38
  version: "0.5.8"
26
39
  cache-suffix: "lint"
27
- - run: uv python install 3.12
40
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
41
+ with:
42
+ python-version: "3.12"
28
43
  - run: uv sync --frozen
29
44
  - run: uv run ruff check .
30
45
  - run: uv run ruff format --check .
31
46
 
32
47
  test:
33
48
  runs-on: ubuntu-latest
49
+ timeout-minutes: 20
34
50
  steps:
51
+ - name: Harden Runner
52
+ uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
53
+ with:
54
+ egress-policy: audit
35
55
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
36
- - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
56
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
37
57
  with:
38
58
  version: "0.5.8"
39
59
  cache-suffix: "test"
40
- - run: uv python install 3.12
60
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
61
+ with:
62
+ python-version: "3.12"
41
63
  - run: uv sync --frozen
42
64
  - run: uv run pytest
43
65
 
@@ -50,12 +72,19 @@ jobs:
50
72
  # fixed budget per run, enough to catch a crash on the next code change.
51
73
  fuzz:
52
74
  runs-on: ubuntu-latest
75
+ timeout-minutes: 15
53
76
  steps:
77
+ - name: Harden Runner
78
+ uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
79
+ with:
80
+ egress-policy: audit
54
81
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
55
- - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
82
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
56
83
  with:
57
84
  version: "0.5.8"
58
- - run: uv python install 3.12
85
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
86
+ with:
87
+ python-version: "3.12"
59
88
  - run: uv sync --frozen --group fuzz
60
89
  - run: uv run python fuzz/fuzz_models_and_callback.py -max_total_time=30 -rss_limit_mb=1024
61
90
 
@@ -63,11 +92,16 @@ jobs:
63
92
  needs: [lint, test]
64
93
  if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
65
94
  runs-on: ubuntu-latest
95
+ timeout-minutes: 20
66
96
  permissions:
67
97
  contents: write
68
98
  outputs:
69
99
  published: ${{ steps.semrel.outputs.new_release_published }}
70
100
  steps:
101
+ - name: Harden Runner
102
+ uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
103
+ with:
104
+ egress-policy: audit
71
105
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
72
106
  with:
73
107
  fetch-depth: 0
@@ -99,14 +133,10 @@ jobs:
99
133
  git fetch origin main
100
134
  git checkout -B main origin/main
101
135
  - id: semrel
102
- uses: cycjimmy/semantic-release-action@b12c8f6015dc215fe37bc154d4ad456dd3833c90 # v6.0.0
136
+ uses: lukislp/ci-workflows/.github/actions/semantic-release@045f17628d155f7e56c2f6ebdbd473b31e247112 # v1.6.0
103
137
  with:
104
- dry_run: true
105
- extra_plugins: |
106
- @semantic-release/changelog@7.0.0
107
- @semantic-release/git@11.0.1
108
- env:
109
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
138
+ dry-run: true
139
+ github-token: ${{ secrets.GITHUB_TOKEN }}
110
140
  - name: No release needed for this push
111
141
  if: steps.semrel.outputs.new_release_published != 'true'
112
142
  run: |
@@ -116,11 +146,16 @@ jobs:
116
146
  needs: [get-version]
117
147
  if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && needs.get-version.outputs.published == 'true'
118
148
  runs-on: ubuntu-latest
149
+ timeout-minutes: 20
119
150
  permissions:
120
151
  contents: write
121
152
  issues: write
122
153
  pull-requests: write
123
154
  steps:
155
+ - name: Harden Runner
156
+ uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
157
+ with:
158
+ egress-policy: audit
124
159
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
125
160
  with:
126
161
  fetch-depth: 0
@@ -148,13 +183,9 @@ jobs:
148
183
  git remote set-url origin "git@github.com:${{ github.repository }}.git"
149
184
  echo "GIT_SSH_COMMAND=ssh -i ~/.ssh/semantic_release -o IdentitiesOnly=yes" >> "$GITHUB_ENV"
150
185
  - id: semrel
151
- uses: cycjimmy/semantic-release-action@b12c8f6015dc215fe37bc154d4ad456dd3833c90 # v6.0.0
186
+ uses: lukislp/ci-workflows/.github/actions/semantic-release@045f17628d155f7e56c2f6ebdbd473b31e247112 # v1.6.0
152
187
  with:
153
- extra_plugins: |
154
- @semantic-release/changelog@7.0.0
155
- @semantic-release/git@11.0.1
156
- env:
157
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
188
+ github-token: ${{ secrets.GITHUB_TOKEN }}
158
189
  continue-on-error: true
159
190
  - if: steps.semrel.outcome == 'failure'
160
191
  name: "Diagnose before retrying (expected: an out-of-band push landed since checkout)"
@@ -169,13 +200,9 @@ jobs:
169
200
  fi
170
201
  git checkout -B main origin/main
171
202
  - if: steps.semrel.outcome == 'failure'
172
- uses: cycjimmy/semantic-release-action@b12c8f6015dc215fe37bc154d4ad456dd3833c90 # v6.0.0
203
+ uses: lukislp/ci-workflows/.github/actions/semantic-release@045f17628d155f7e56c2f6ebdbd473b31e247112 # v1.6.0
173
204
  with:
174
- extra_plugins: |
175
- @semantic-release/changelog@7.0.0
176
- @semantic-release/git@11.0.1
177
- env:
178
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
205
+ github-token: ${{ secrets.GITHUB_TOKEN }}
179
206
 
180
207
  # Runs after semantic-release so the checkout below lands on the freshly tagged commit -
181
208
  # hatch-vcs then resolves an exact version (e.g. "1.2.0"), not a "*.dev0+g<hash>" one, which
@@ -184,18 +211,25 @@ jobs:
184
211
  needs: [get-version, semantic-release]
185
212
  if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && needs.get-version.outputs.published == 'true'
186
213
  runs-on: ubuntu-latest
214
+ timeout-minutes: 45
187
215
  environment: pypi
188
216
  permissions:
189
217
  id-token: write # trusted publishing (OIDC) - no PyPI token/secret needed
190
218
  steps:
219
+ - name: Harden Runner
220
+ uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
221
+ with:
222
+ egress-policy: audit
191
223
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
192
224
  with:
193
225
  ref: main
194
226
  fetch-depth: 0 # full history + tags, so hatch-vcs can find the tag just created
195
- - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
227
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
196
228
  with:
197
229
  version: "0.5.8"
198
230
  cache-suffix: "publish"
199
- - run: uv python install 3.12
231
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
232
+ with:
233
+ python-version: "3.12"
200
234
  - run: uv build
201
235
  - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
@@ -0,0 +1,22 @@
1
+ name: Dependabot auto-merge
2
+
3
+ # Thin caller of the shared implementation in lukislp/ci-workflows (auto-merge of Dependabot
4
+ # patch/minor updates, update-stale for every PR that is behind the tip) - the triggers stay
5
+ # here because a reusable workflow cannot declare them for the caller. Needs the AUTOMERGE_TOKEN
6
+ # repository secret (fine-grained PAT, contents + pull requests write).
7
+ on:
8
+ pull_request_target:
9
+ types: [opened, synchronize, reopened, auto_merge_enabled]
10
+ schedule:
11
+ - cron: "23 * * * *"
12
+ push:
13
+ branches: [main]
14
+
15
+ permissions:
16
+ pull-requests: read
17
+
18
+ jobs:
19
+ dependabot:
20
+ uses: lukislp/ci-workflows/.github/workflows/dependabot-auto-merge.yml@045f17628d155f7e56c2f6ebdbd473b31e247112 # v1.6.0
21
+ secrets:
22
+ AUTOMERGE_TOKEN: ${{ secrets.AUTOMERGE_TOKEN }}
@@ -0,0 +1,20 @@
1
+ name: Dependabot lock files
2
+
3
+ # Thin caller of the shared implementation in lukislp/ci-workflows: regenerates the lock files
4
+ # on Dependabot's own PRs with the CI tool versions and pushes them back onto the PR branch.
5
+ # Plain pull_request on purpose (never pull_request_target); AUTOMERGE_TOKEN is stored as a
6
+ # Dependabot secret, which only Dependabot-triggered runs can read.
7
+ on:
8
+ pull_request:
9
+ types: [opened, synchronize, reopened]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ lockfiles:
16
+ uses: lukislp/ci-workflows/.github/workflows/dependabot-lockfiles.yml@045f17628d155f7e56c2f6ebdbd473b31e247112 # v1.6.0
17
+ with:
18
+ uv-version: "0.5.8"
19
+ secrets:
20
+ AUTOMERGE_TOKEN: ${{ secrets.AUTOMERGE_TOKEN }}
@@ -0,0 +1,27 @@
1
+ name: Dependency review
2
+
3
+ # Thin caller of the shared implementation in lukislp/ci-workflows - the triggers stay here
4
+ # because a reusable workflow cannot declare them for the caller. Compares the base and head
5
+ # dependency graphs of a pull request and fails it when the PR introduces a dependency with a
6
+ # known advisory, which Dependabot alerts would otherwise only report after the merge. The
7
+ # check name in the branch ruleset is "review / dependency-review".
8
+ on:
9
+ pull_request:
10
+ types: [opened, synchronize, reopened]
11
+
12
+ # One run per PR: a newer push cancels the run it supersedes.
13
+ concurrency:
14
+ group: dependency-review-${{ github.event.pull_request.number || github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ permissions:
18
+ contents: read
19
+
20
+ jobs:
21
+ review:
22
+ uses: lukislp/ci-workflows/.github/workflows/dependency-review.yml@045f17628d155f7e56c2f6ebdbd473b31e247112 # v1.6.0
23
+ # pull-requests: write is what the summary comment needs; the called workflow keeps
24
+ # contents at read.
25
+ permissions:
26
+ contents: read
27
+ pull-requests: write
@@ -16,6 +16,7 @@ permissions: read-all
16
16
  jobs:
17
17
  analysis:
18
18
  runs-on: ubuntu-latest
19
+ timeout-minutes: 15
19
20
  permissions:
20
21
  security-events: write
21
22
  id-token: write
@@ -28,6 +29,6 @@ jobs:
28
29
  results_file: results.sarif
29
30
  results_format: sarif
30
31
  publish_results: true
31
- - uses: github/codeql-action/upload-sarif@faaca9a8f6edddba5725ffe5adefdab6669a2eca # v3.38.0
32
+ - uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
32
33
  with:
33
34
  sarif_file: results.sarif
@@ -1,3 +1,17 @@
1
+ ## [1.9.4](https://github.com/lukislp/studylife-cli/compare/v1.9.3...v1.9.4) (2026-09-20)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **ci:** add Harden Runner in audit mode to every job ([#42](https://github.com/lukislp/studylife-cli/issues/42)) ([be13fec](https://github.com/lukislp/studylife-cli/commit/be13fec38dc3418643f6f5a8b05e288df2ebd34f))
7
+
8
+ ## [1.9.3](https://github.com/lukislp/studylife-cli/compare/v1.9.2...v1.9.3) (2026-09-17)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **ci:** bump astral-sh/setup-uv from 10.0.1 to 10.1.0 ([5248a13](https://github.com/lukislp/studylife-cli/commit/5248a133ecbaf6b9a1bb237432dd94e574de174e))
14
+
1
15
  ## [1.9.2](https://github.com/lukislp/studylife-cli/compare/v1.9.1...v1.9.2) (2026-09-12)
2
16
 
3
17
 
@@ -0,0 +1,138 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the overall
26
+ community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or advances of
31
+ any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ 155678024+lukislp@users.noreply.github.com.
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series of
86
+ actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or permanent
93
+ ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within the
113
+ community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.1, available at
119
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120
+
121
+ Community Impact Guidelines were inspired by
122
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123
+
124
+ For answers to common questions about this code of conduct, see the FAQ at
125
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126
+ [https://www.contributor-covenant.org/translations][translations].
127
+
128
+ [homepage]: https://www.contributor-covenant.org
129
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130
+ [Mozilla CoC]: https://github.com/mozilla/diversity
131
+ [FAQ]: https://www.contributor-covenant.org/faq
132
+ [translations]: https://www.contributor-covenant.org/translations
133
+
134
+ ## Reporting a security issue
135
+
136
+ This document covers conduct. A security vulnerability in the code is not a
137
+ conduct matter - report it privately through the process described in
138
+ [SECURITY.md](SECURITY.md) instead of opening a public issue.
@@ -0,0 +1,65 @@
1
+ # Contributing to StudyLife CLI
2
+
3
+ Thanks for taking the time. StudyLife CLI is a single-maintainer project, so the process is
4
+ deliberately small - but it is the same for every change, including the maintainer's own.
5
+
6
+ ## How changes get in
7
+
8
+ 1. Open an issue first for anything bigger than a typo or an obvious bug fix, so the direction can
9
+ be agreed before you spend time on it. Use the templates under `.github/ISSUE_TEMPLATE/`.
10
+ 2. Fork the repository (or branch, if you have write access) and make your change on a branch.
11
+ 3. Open a pull request against `main`. The pull-request template asks for what changed and why.
12
+ 4. `main` is protected: a PR merges only after the test stage of
13
+ [`.github/workflows/ci.yml`](.github/workflows/ci.yml) is green and the branch is up to date
14
+ with `main` (enable auto-merge and it lands on its own once that is the case). Nobody pushes to
15
+ `main` directly, not even the maintainer.
16
+
17
+ ## What a pull request needs
18
+
19
+ - **Conventional Commits.** The version and the changelog are generated from the commit messages
20
+ (`feat:` = minor release, `fix:` = patch release, `build:`/`ci:`/`docs:`/`test:` = no release).
21
+ A released version is published to PyPI, so the commit type decides what users get.
22
+ Squash-merge keeps the PR title as the commit message, so give the PR a Conventional Commit
23
+ title.
24
+ - **Green required checks.** `lint`, `test` and `review / dependency-review` are required; a red
25
+ one blocks the merge.
26
+ - **Tests for new functionality.** New features and bug fixes come with tests in `tests/`
27
+ (`test_cli.py`, `test_client.py`, `test_login.py`, `test_tui.py`). A PR that adds behaviour
28
+ without a test is asked to add one.
29
+ - **Lint and formatting.** The `lint` job runs `ruff check .` **and** `ruff format --check .`. Run
30
+ both before pushing; `ruff check` passing does not mean the formatting is clean.
31
+ - **Lockfile.** CI installs with `uv sync --frozen`, so a dependency change means committing the
32
+ updated `uv.lock` alongside `pyproject.toml`.
33
+ - **Command surface.** This is a user-facing CLI. A renamed command, flag or output format is a
34
+ breaking change for anyone scripting against it - call it out in the PR body so the release
35
+ notes carry it.
36
+
37
+ ## Running things locally
38
+
39
+ Python 3.12 or newer, with [uv](https://docs.astral.sh/uv/).
40
+
41
+ ```bash
42
+ uv sync
43
+ uv run pytest
44
+ uv run ruff check .
45
+ uv run ruff format --check .
46
+ ```
47
+
48
+ The fuzz target is Linux-only (`atheris` publishes no Windows wheel):
49
+
50
+ ```bash
51
+ uv sync --frozen --group fuzz
52
+ uv run python fuzz/fuzz_models_and_callback.py -max_total_time=30 -rss_limit_mb=1024
53
+ ```
54
+
55
+ ## Releases
56
+
57
+ Merging a `feat:` or `fix:` to `main` cuts a release and publishes the built distributions to PyPI
58
+ via trusted publishing. Users install with `pip install studylife-cli` or
59
+ `pipx install studylife-cli`.
60
+
61
+ ## Security issues
62
+
63
+ Please do not open a public issue for a vulnerability - use the private reporting path described
64
+ in [SECURITY.md](SECURITY.md). The [Code of Conduct](CODE_OF_CONDUCT.md) applies to every
65
+ interaction in this repository.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: studylife-cli
3
- Version: 1.9.2
3
+ Version: 1.9.4
4
4
  Summary: Command-line client for StudyLife (self-hosted study organizer) - notes, sessions, course goals, and webhooks from your terminal.
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -0,0 +1,8 @@
1
+ version: 2
2
+
3
+ githubApp:
4
+ enabled: true
5
+ dependencyOverviewEnabled: true
6
+ pullRequestAlertsEnabled: true
7
+ projectReportsEnabled: true
8
+ disableCommentsAndCheckRuns: false
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '1.9.2'
22
- __version_tuple__ = version_tuple = (1, 9, 2)
21
+ __version__ = version = '1.9.4'
22
+ __version_tuple__ = version_tuple = (1, 9, 4)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -405,7 +405,7 @@ wheels = [
405
405
 
406
406
  [[package]]
407
407
  name = "studylife-cli"
408
- version = "1.9.2.dev9+g1002804fa.d20260912"
408
+ version = "1.9.3.dev83+g7ef281223.d20260917"
409
409
  source = { editable = "." }
410
410
  dependencies = [
411
411
  { name = "httpx" },
@@ -1,77 +0,0 @@
1
- name: Dependabot auto-merge
2
-
3
- # Merges Dependabot patch and minor updates once every required check is green; majors stay
4
- # manual. Runs on pull_request_target so the base branch's workflow definition and the repo
5
- # secrets apply (a Dependabot-triggered pull_request run gets neither). Merges with
6
- # AUTOMERGE_TOKEN, a fine-grained PAT (contents + pull requests: write): a merge performed with
7
- # GITHUB_TOKEN would never start the release workflow, because GitHub does not run workflows for
8
- # events caused by GITHUB_TOKEN. Deliberately no checkout - PR code is never executed here.
9
- on:
10
- pull_request_target:
11
- # auto_merge_enabled: a PR that is already behind when someone arms auto-merge would
12
- # otherwise wait for the next push to be brought up to date.
13
- types: [opened, synchronize, reopened, auto_merge_enabled]
14
- # Safety net for a PR armed while behind when nothing else is pushed for a while.
15
- schedule:
16
- - cron: "23 * * * *"
17
- # The default branch requires pull requests to be up to date before they merge (ruleset).
18
- # Every push to it therefore leaves the open Dependabot PRs "behind"; the update-stale job
19
- # below brings them back onto the tip so their auto-merge can proceed without a manual rebase.
20
- push:
21
- branches: [main]
22
-
23
- # GITHUB_TOKEN only reads PR metadata; the merge itself runs with AUTOMERGE_TOKEN (above).
24
- permissions:
25
- pull-requests: read
26
-
27
- jobs:
28
- auto-merge:
29
- if: github.event_name == 'pull_request_target' && github.event.action != 'auto_merge_enabled' && github.actor == 'dependabot[bot]'
30
- runs-on: ubuntu-latest
31
- env:
32
- HAS_TOKEN: ${{ secrets.AUTOMERGE_TOKEN != '' }}
33
- steps:
34
- - id: meta
35
- uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0
36
- with:
37
- github-token: ${{ secrets.GITHUB_TOKEN }}
38
- - if: env.HAS_TOKEN == 'true' && (steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor')
39
- env:
40
- GH_TOKEN: ${{ secrets.AUTOMERGE_TOKEN }}
41
- run: gh pr merge --auto --merge "${{ github.event.pull_request.html_url }}"
42
- - if: env.HAS_TOKEN != 'true'
43
- run: echo "AUTOMERGE_TOKEN is not set - leaving this PR for a manual merge"
44
-
45
- update-stale:
46
- if: github.event_name == 'push' || github.event_name == 'schedule' || github.event.action == 'auto_merge_enabled'
47
- runs-on: ubuntu-latest
48
- env:
49
- HAS_TOKEN: ${{ secrets.AUTOMERGE_TOKEN != '' }}
50
- steps:
51
- - if: env.HAS_TOKEN == 'true'
52
- env:
53
- GH_TOKEN: ${{ secrets.AUTOMERGE_TOKEN }}
54
- REPO: ${{ github.repository }}
55
- # The default branch requires PRs to be up to date before they merge, so every push
56
- # here leaves the other open PRs "behind". This brings them back onto the tip: every
57
- # non-draft PR that has auto-merge enabled or was opened by a person (a Dependabot PR
58
- # left for a manual decision, i.e. a major bump, is not rebuilt on every push - whoever
59
- # merges it updates it). GitHub computes the merge state lazily after a push, so UNKNOWN
60
- # is polled for a while; DIRTY (conflicts) cannot be updated automatically.
61
- run: |
62
- for n in $(gh pr list --repo "$REPO" --state open --json number --jq '.[].number'); do
63
- info="$(gh pr view "$n" --repo "$REPO" --json isDraft,author,autoMergeRequest --jq '"\(.isDraft) \(.author.login) \(.autoMergeRequest != null)"')"
64
- set -- $info
65
- draft=$1; author=$2; auto=$3
66
- [ "$draft" = "true" ] && continue
67
- if [ "$auto" != "true" ] && [ "$author" = "app/dependabot" ]; then continue; fi
68
- for attempt in 1 2 3 4 5 6; do
69
- state="$(gh pr view "$n" --repo "$REPO" --json mergeStateStatus --jq .mergeStateStatus)"
70
- [ "$state" != "UNKNOWN" ] && break
71
- sleep 10
72
- done
73
- echo "#$n ($author, auto-merge=$auto): $state"
74
- if [ "$state" = "BEHIND" ]; then
75
- gh api -X PUT "repos/$REPO/pulls/$n/update-branch" >/dev/null && echo " updated onto main" || echo "::warning::could not update #$n"
76
- fi
77
- done
@@ -1,80 +0,0 @@
1
- name: Dependabot lock files
2
-
3
- # Dependabot regenerates the lock file of the project whose manifest it bumped, but not the
4
- # lock files of the projects that depend on it (NuGet records a reference's dependencies in
5
- # the referencing project's packages.lock.json) - and its uv lock output has shipped unparsable
6
- # files. Locked-mode restores then fail on the PR. This job runs on Dependabot's own PRs,
7
- # regenerates every lock file with the same tool versions CI uses and pushes the result back
8
- # onto the PR branch, after which the normal CI run and the auto-merge proceed.
9
- #
10
- # Deliberately a plain pull_request run (no pull_request_target): the PR's own restore runs in
11
- # the untrusted context with a read-only GITHUB_TOKEN, and the only credential involved - the
12
- # push token - is a Dependabot secret, which GitHub exposes solely to runs Dependabot triggered
13
- # and only to the single step that pushes. Nothing from the PR ever sees it.
14
- on:
15
- pull_request:
16
- types: [opened, synchronize, reopened]
17
-
18
- permissions:
19
- contents: read
20
-
21
- jobs:
22
- refresh:
23
- if: github.actor == 'dependabot[bot]'
24
- runs-on: ubuntu-latest
25
- env:
26
- HAS_TOKEN: ${{ secrets.AUTOMERGE_TOKEN != '' }}
27
- HEAD_REF: ${{ github.head_ref }}
28
- steps:
29
- - if: env.HAS_TOKEN != 'true'
30
- run: echo "AUTOMERGE_TOKEN is not set as a Dependabot secret - lock files are not refreshed automatically"
31
- - if: env.HAS_TOKEN == 'true'
32
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
33
- with:
34
- ref: ${{ github.head_ref }}
35
- # Full history so the base branch's uv.lock is available locally (private repos
36
- # cannot be fetched anonymously later, and the push token stays out of this step).
37
- fetch-depth: 0
38
- persist-credentials: false
39
- - if: env.HAS_TOKEN == 'true' && hashFiles('**/packages.lock.json') != ''
40
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
41
- with:
42
- dotnet-version: "10.0.x"
43
- - if: env.HAS_TOKEN == 'true' && hashFiles('**/packages.lock.json') != ''
44
- name: Regenerate every packages.lock.json
45
- run: |
46
- set -eu
47
- for lock in $(git ls-files '**/packages.lock.json' 'packages.lock.json'); do
48
- proj="$(ls "$(dirname "$lock")"/*.csproj | head -1)"
49
- echo "restoring $proj"
50
- dotnet restore "$proj" --force-evaluate -p:RestoreLockedMode=false
51
- done
52
- - if: env.HAS_TOKEN == 'true' && hashFiles('uv.lock') != ''
53
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
54
- with:
55
- version: "0.5.8"
56
- - if: env.HAS_TOKEN == 'true' && hashFiles('uv.lock') != ''
57
- name: Regenerate uv.lock
58
- env:
59
- BASE_REF: ${{ github.base_ref }}
60
- run: |
61
- # Dependabot's own uv.lock output has been unparsable, and `uv lock` refuses to start
62
- # from a broken file - so resolve from the base branch's lock plus the PR's pyproject.
63
- git show "origin/$BASE_REF:uv.lock" > uv.lock
64
- uv python install 3.12
65
- uv lock
66
- - if: env.HAS_TOKEN == 'true'
67
- name: Push the refreshed lock files back onto the PR
68
- env:
69
- PUSH_TOKEN: ${{ secrets.AUTOMERGE_TOKEN }}
70
- run: |
71
- # Only tracked files change here (the lock files); untracked build output stays out.
72
- git add -u
73
- if git diff --cached --quiet; then
74
- echo "lock files already consistent"
75
- exit 0
76
- fi
77
- git config user.name "lukislp"
78
- git config user.email "koerber.lukas@t-online.de"
79
- git commit -m "chore(deps): refresh the lock files after the Dependabot update"
80
- git push "https://x-access-token:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "HEAD:refs/heads/${HEAD_REF}"
File without changes
File without changes
File without changes
File without changes