Skip to content

Commit eb23a8e

Browse files
committed
feat: initial release
0 parents  commit eb23a8e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+6152
-0
lines changed

.codecov.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
coverage:
2+
status:
3+
project:
4+
default:
5+
# Allow up to 2% drop before CI fails
6+
threshold: 2%
7+
8+
# Exclude files whose core logic requires live network I/O or in-process
9+
# binary replacement - these cannot be safely exercised in unit tests.
10+
ignore:
11+
- "src/main.rs"
12+
- "src/cli.rs"
13+
- "src/self_update.rs"
14+
- "src/uninstall.rs"
15+
16+
comment:
17+
layout: "reach,diff,flags,files"
18+
behavior: default

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @Logic-py
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Bug Report
2+
description: Something isn't working correctly
3+
labels: [ "bug" ]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Thank you for reporting a bug. Please fill in as much detail as possible.
9+
10+
- type: textarea
11+
id: description
12+
attributes:
13+
label: Description
14+
description: A clear description of the bug.
15+
validations:
16+
required: true
17+
18+
- type: textarea
19+
id: reproduction
20+
attributes:
21+
label: Steps to reproduce
22+
description: Commands run, file contents used, etc.
23+
placeholder: |
24+
1. Create a `pyproject.toml` with ...
25+
2. Run `pycu ...`
26+
3. See error
27+
validations:
28+
required: true
29+
30+
- type: textarea
31+
id: expected
32+
attributes:
33+
label: Expected behavior
34+
description: What did you expect to happen?
35+
validations:
36+
required: true
37+
38+
- type: textarea
39+
id: actual
40+
attributes:
41+
label: Actual behavior
42+
description: What actually happened? Include the full output or error message.
43+
validations:
44+
required: true
45+
46+
- type: input
47+
id: version
48+
attributes:
49+
label: pycu version
50+
description: Run `pycu --version`
51+
placeholder: "0.2.6"
52+
validations:
53+
required: true
54+
55+
- type: dropdown
56+
id: os
57+
attributes:
58+
label: Operating system
59+
options:
60+
- Linux
61+
- macOS
62+
- Windows
63+
validations:
64+
required: true
65+
66+
- type: textarea
67+
id: additional
68+
attributes:
69+
label: Additional context
70+
description: Anything else that might be relevant.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Feature Request
2+
description: Suggest an improvement or new capability
3+
labels: [ "enhancement" ]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Have an idea? Describe it below. For large changes, opening an issue first to discuss the approach before
9+
submitting a PR is appreciated.
10+
11+
- type: textarea
12+
id: problem
13+
attributes:
14+
label: Problem or motivation
15+
description: What problem does this solve, or what need does it address?
16+
placeholder: "I often need to... but currently pycu doesn't support..."
17+
validations:
18+
required: true
19+
20+
- type: textarea
21+
id: solution
22+
attributes:
23+
label: Proposed solution
24+
description: Describe the feature or change you would like.
25+
validations:
26+
required: true
27+
28+
- type: textarea
29+
id: alternatives
30+
attributes:
31+
label: Alternatives considered
32+
description: Any other approaches you considered, and why you prefer the proposed one.
33+
34+
- type: textarea
35+
id: additional
36+
attributes:
37+
label: Additional context
38+
description: Examples, links, screenshots, or anything else relevant.

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
## Summary
2+
3+
<!-- What does this PR change and why? -->
4+
5+
## Type of change
6+
7+
- [ ] Bug fix
8+
- [ ] New feature
9+
- [ ] Refactor / cleanup
10+
- [ ] Documentation
11+
- [ ] CI / tooling
12+
13+
## Checklist
14+
15+
- [ ] `cargo fmt` applied
16+
- [ ] `cargo clippy --all-targets --all-features -- -D warnings` passes
17+
- [ ] `cargo test --all-features` passes
18+
- [ ] Tests added or updated for changed logic
19+
- [ ] Public API changes documented
20+
- [ ] `CHANGELOG.md` updated (for user-visible changes)

.github/dependabot.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
version: 2
2+
3+
updates:
4+
# Keep Rust dependencies up to date
5+
- package-ecosystem: "cargo"
6+
directory: "/"
7+
schedule:
8+
interval: "weekly"
9+
day: "monday"
10+
labels:
11+
- "dependencies"
12+
open-pull-requests-limit: 10
13+
14+
# Keep GitHub Actions up to date
15+
- package-ecosystem: "github-actions"
16+
directory: "/"
17+
schedule:
18+
interval: "weekly"
19+
day: "monday"
20+
labels:
21+
- "dependencies"
22+
open-pull-requests-limit: 10

.github/workflows/ci.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ "**" ]
6+
pull_request:
7+
8+
jobs:
9+
test:
10+
name: Test
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v6
14+
15+
- uses: dtolnay/rust-toolchain@stable
16+
with:
17+
components: clippy, rustfmt
18+
19+
- uses: Swatinem/rust-cache@v2
20+
21+
- run: cargo fmt --check
22+
- run: cargo clippy --all-targets --all-features -- -D warnings
23+
- run: cargo test --all-features
24+
25+
coverage:
26+
name: Coverage
27+
runs-on: ubuntu-latest
28+
steps:
29+
- uses: actions/checkout@v6
30+
31+
- uses: dtolnay/rust-toolchain@stable
32+
with:
33+
components: llvm-tools-preview
34+
35+
- uses: Swatinem/rust-cache@v2
36+
37+
- uses: taiki-e/install-action@cargo-llvm-cov
38+
39+
- run: cargo llvm-cov --all-features --lcov --output-path lcov.info
40+
41+
- uses: codecov/codecov-action@v5
42+
with:
43+
files: lcov.info
44+
token: ${{ secrets.CODECOV_TOKEN }}

.github/workflows/release.yml

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
# --- 1. Read version from Cargo.toml; skip if this version was already released ---
12+
check-version:
13+
name: Check version
14+
runs-on: ubuntu-latest
15+
outputs:
16+
tag: ${{ steps.read.outputs.tag }}
17+
should_release: ${{ steps.check.outputs.should_release }}
18+
steps:
19+
- uses: actions/checkout@v6
20+
21+
- name: Read version
22+
id: read
23+
run: |
24+
VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
25+
echo "tag=${VERSION}" >> "$GITHUB_OUTPUT"
26+
27+
- name: Check if release already exists
28+
id: check
29+
env:
30+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
run: |
32+
if gh release view "${{ steps.read.outputs.tag }}" \
33+
--repo "${{ github.repository }}" > /dev/null 2>&1; then
34+
echo "Release ${{ steps.read.outputs.tag }} already exists - skipping."
35+
echo "should_release=false" >> "$GITHUB_OUTPUT"
36+
else
37+
echo "should_release=true" >> "$GITHUB_OUTPUT"
38+
fi
39+
40+
# --- 2. Run tests (gate the release on green tests) ----------------------------
41+
test:
42+
name: Test
43+
needs: check-version
44+
if: needs.check-version.outputs.should_release == 'true'
45+
runs-on: ubuntu-latest
46+
steps:
47+
- uses: actions/checkout@v6
48+
- uses: dtolnay/rust-toolchain@stable
49+
- uses: Swatinem/rust-cache@v2
50+
- run: cargo test
51+
52+
# --- 3. Build for every target platform ----------------------------------------
53+
build:
54+
name: Build · ${{ matrix.target }}
55+
needs: [ check-version, test ]
56+
runs-on: ${{ matrix.os }}
57+
strategy:
58+
fail-fast: false
59+
matrix:
60+
include:
61+
- { target: x86_64-unknown-linux-musl, os: ubuntu-latest, archive: tar.gz }
62+
- { target: aarch64-unknown-linux-musl, os: ubuntu-latest, archive: tar.gz }
63+
- { target: x86_64-apple-darwin, os: macos-latest, archive: tar.gz }
64+
- { target: aarch64-apple-darwin, os: macos-latest, archive: tar.gz }
65+
- { target: x86_64-pc-windows-msvc, os: windows-latest, archive: zip }
66+
67+
steps:
68+
- uses: actions/checkout@v6
69+
70+
- uses: dtolnay/rust-toolchain@stable
71+
with:
72+
targets: ${{ matrix.target }}
73+
74+
- uses: Swatinem/rust-cache@v2
75+
with:
76+
key: ${{ matrix.target }}
77+
78+
# Linux: cargo-zigbuild gives us static musl binaries for both x86_64 and
79+
# aarch64 without needing Docker or a cross-compiler toolchain.
80+
- name: Cache cargo-zigbuild
81+
if: runner.os == 'Linux'
82+
id: cache-zigbuild
83+
uses: actions/cache@v4
84+
with:
85+
path: ~/.cargo/bin/cargo-zigbuild
86+
key: cargo-zigbuild-${{ runner.os }}
87+
88+
- name: Install Zig
89+
if: runner.os == 'Linux'
90+
run: pip install ziglang
91+
92+
- name: Install cargo-zigbuild
93+
if: runner.os == 'Linux' && steps.cache-zigbuild.outputs.cache-hit != 'true'
94+
run: cargo install cargo-zigbuild --locked
95+
96+
- name: Build (Linux)
97+
if: runner.os == 'Linux'
98+
run: cargo zigbuild --release --target ${{ matrix.target }}
99+
100+
# macOS and Windows use standard cargo - the runner already has the right toolchain.
101+
- name: Build (macOS / Windows)
102+
if: runner.os != 'Linux'
103+
run: cargo build --release --target ${{ matrix.target }}
104+
105+
# -- Package ---------------------------------------------------------------
106+
- name: Package (Unix)
107+
if: runner.os != 'Windows'
108+
run: |
109+
tar -czf pycu-${{ matrix.target }}.tar.gz \
110+
-C target/${{ matrix.target }}/release pycu
111+
112+
- name: Package (Windows)
113+
if: runner.os == 'Windows'
114+
shell: pwsh
115+
run: |
116+
Compress-Archive `
117+
-Path "target\${{ matrix.target }}\release\pycu.exe" `
118+
-DestinationPath "pycu-${{ matrix.target }}.zip"
119+
120+
- uses: actions/upload-artifact@v7
121+
with:
122+
name: pycu-${{ matrix.target }}
123+
path: pycu-${{ matrix.target }}.${{ matrix.archive }}
124+
if-no-files-found: error
125+
126+
# --- 4. Create the GitHub Release and attach all binaries ----------------------
127+
release:
128+
name: Publish release
129+
needs: [ check-version, build ]
130+
runs-on: ubuntu-latest
131+
steps:
132+
- uses: actions/checkout@v6
133+
134+
- uses: actions/download-artifact@v7
135+
with:
136+
path: artifacts
137+
merge-multiple: true
138+
139+
- name: Generate SHA256 checksums
140+
run: |
141+
cd artifacts
142+
sha256sum * > checksums.sha256
143+
cat checksums.sha256
144+
145+
- name: Create GitHub Release
146+
env:
147+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
148+
run: |
149+
gh release create "${{ needs.check-version.outputs.tag }}" \
150+
--title "${{ needs.check-version.outputs.tag }}" \
151+
--generate-notes \
152+
artifacts/*
153+
154+
# --- 5. Publish to crates.io ------------------------------------------------
155+
publish-crate:
156+
name: Publish to crates.io
157+
needs: [ check-version, release ]
158+
runs-on: ubuntu-latest
159+
steps:
160+
- uses: actions/checkout@v6
161+
- uses: dtolnay/rust-toolchain@stable
162+
- uses: Swatinem/rust-cache@v2
163+
- name: Publish
164+
run: cargo publish --token ${{ secrets.CRATES_IO_TOKEN }}

0 commit comments

Comments
 (0)