@ifi/oh-pi-skills 0.2.8 → 0.2.10
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/package.json +1 -1
- package/skills/btw/SKILL.md +149 -0
- package/skills/flutter-serverpod-mvp/SKILL.md +199 -0
- package/skills/rust-workspace-bootstrap/SKILL.md +86 -0
- package/skills/rust-workspace-bootstrap/scaffold.js +222 -0
- package/skills/rust-workspace-bootstrap/template/.cargo/config.toml +7 -0
- package/skills/rust-workspace-bootstrap/template/.changeset/.gitkeep +0 -0
- package/skills/rust-workspace-bootstrap/template/.envrc +7 -0
- package/skills/rust-workspace-bootstrap/template/.github/actions/devenv/action.yml +42 -0
- package/skills/rust-workspace-bootstrap/template/.github/workflows/ci.yml +130 -0
- package/skills/rust-workspace-bootstrap/template/.github/workflows/coverage.yml +45 -0
- package/skills/rust-workspace-bootstrap/template/.github/workflows/docs-pages.yml +60 -0
- package/skills/rust-workspace-bootstrap/template/.github/workflows/release-preview.yml +52 -0
- package/skills/rust-workspace-bootstrap/template/.github/workflows/release.yml +87 -0
- package/skills/rust-workspace-bootstrap/template/.github/workflows/semver.yml +63 -0
- package/skills/rust-workspace-bootstrap/template/Cargo.toml +64 -0
- package/skills/rust-workspace-bootstrap/template/changelog.md +3 -0
- package/skills/rust-workspace-bootstrap/template/clippy.toml +1 -0
- package/skills/rust-workspace-bootstrap/template/crates/__CLI_CRATE__/Cargo.toml +20 -0
- package/skills/rust-workspace-bootstrap/template/crates/__CLI_CRATE__/src/main.rs +21 -0
- package/skills/rust-workspace-bootstrap/template/crates/__CORE_CRATE__/Cargo.toml +15 -0
- package/skills/rust-workspace-bootstrap/template/crates/__CORE_CRATE__/src/lib.rs +32 -0
- package/skills/rust-workspace-bootstrap/template/deny.toml +18 -0
- package/skills/rust-workspace-bootstrap/template/devenv.nix +214 -0
- package/skills/rust-workspace-bootstrap/template/devenv.yaml +10 -0
- package/skills/rust-workspace-bootstrap/template/docs/book.toml +6 -0
- package/skills/rust-workspace-bootstrap/template/docs/src/SUMMARY.md +3 -0
- package/skills/rust-workspace-bootstrap/template/docs/src/index.md +3 -0
- package/skills/rust-workspace-bootstrap/template/dprint.json +40 -0
- package/skills/rust-workspace-bootstrap/template/knope.toml +73 -0
- package/skills/rust-workspace-bootstrap/template/readme.md +77 -0
- package/skills/rust-workspace-bootstrap/template/rust-toolchain.toml +4 -0
- package/skills/rust-workspace-bootstrap/template/rustfmt.toml +21 -0
- package/skills/rust-workspace-bootstrap/template/scripts/release.sh +61 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: devenv
|
|
2
|
+
description: Setup development environment with devenv
|
|
3
|
+
inputs:
|
|
4
|
+
github-token:
|
|
5
|
+
description: Provide a GitHub token
|
|
6
|
+
required: true
|
|
7
|
+
cache-version:
|
|
8
|
+
description: Cache version for dependency keys
|
|
9
|
+
required: false
|
|
10
|
+
default: "v1"
|
|
11
|
+
|
|
12
|
+
runs:
|
|
13
|
+
using: composite
|
|
14
|
+
steps:
|
|
15
|
+
- name: cache rust dependencies
|
|
16
|
+
uses: Swatinem/rust-cache@v2
|
|
17
|
+
with:
|
|
18
|
+
prefix-key: "${{ inputs.cache-version }}"
|
|
19
|
+
|
|
20
|
+
- name: cache cargo binaries
|
|
21
|
+
uses: actions/cache@v4
|
|
22
|
+
with:
|
|
23
|
+
path: ./.bin
|
|
24
|
+
key: ${{ runner.os }}-cargo-bin-${{ inputs.cache-version }}-${{ env.RUSTUP_TOOLCHAIN }}-${{ hashFiles('rust-toolchain.toml', 'Cargo.toml') }}
|
|
25
|
+
restore-keys: |
|
|
26
|
+
${{ runner.os }}-cargo-bin-${{ inputs.cache-version }}-
|
|
27
|
+
|
|
28
|
+
- name: install nix
|
|
29
|
+
uses: cachix/install-nix-action@v31
|
|
30
|
+
with:
|
|
31
|
+
github_access_token: ${{ inputs.github-token }}
|
|
32
|
+
|
|
33
|
+
- name: setup nix environment
|
|
34
|
+
run: |
|
|
35
|
+
nix profile add --accept-flake-config nixpkgs#cachix
|
|
36
|
+
cachix use devenv
|
|
37
|
+
nix profile add nixpkgs#devenv
|
|
38
|
+
shell: bash
|
|
39
|
+
|
|
40
|
+
- name: install dependencies
|
|
41
|
+
run: install:cargo:bin
|
|
42
|
+
shell: devenv shell -- bash -e {0}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
name: "ci"
|
|
2
|
+
permissions:
|
|
3
|
+
contents: read
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
pull_request:
|
|
9
|
+
branches:
|
|
10
|
+
- main
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
commit-lint:
|
|
18
|
+
timeout-minutes: 15
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- name: checkout repository
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
|
|
26
|
+
- name: validate commit messages
|
|
27
|
+
run: |
|
|
28
|
+
PATTERN='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?: .+'
|
|
29
|
+
|
|
30
|
+
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
|
31
|
+
BASE_SHA='${{ github.event.pull_request.base.sha }}'
|
|
32
|
+
HEAD_SHA='${{ github.event.pull_request.head.sha }}'
|
|
33
|
+
COMMITS=$(git log --format='%s' --no-merges "${BASE_SHA}..${HEAD_SHA}")
|
|
34
|
+
else
|
|
35
|
+
COMMITS=$(git log --format='%s' -1)
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
FAILED=0
|
|
39
|
+
while IFS= read -r msg; do
|
|
40
|
+
[ -z "$msg" ] && continue
|
|
41
|
+
if ! echo "$msg" | grep -qE "$PATTERN"; then
|
|
42
|
+
echo "::error::Invalid commit message: '$msg'"
|
|
43
|
+
FAILED=1
|
|
44
|
+
fi
|
|
45
|
+
done <<< "$COMMITS"
|
|
46
|
+
|
|
47
|
+
if [ "$FAILED" -eq 1 ]; then
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
changeset:
|
|
52
|
+
timeout-minutes: 10
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
if: github.event_name == 'pull_request' || !startsWith(github.event.head_commit.message, 'chore: prepare releases')
|
|
55
|
+
steps:
|
|
56
|
+
- name: checkout repository
|
|
57
|
+
uses: actions/checkout@v4
|
|
58
|
+
|
|
59
|
+
- name: check for changeset
|
|
60
|
+
run: |
|
|
61
|
+
CHANGESETS=$(find .changeset -name '*.md' ! -name 'README.md' 2>/dev/null | wc -l | tr -d ' ')
|
|
62
|
+
if [ "$CHANGESETS" -eq 0 ]; then
|
|
63
|
+
echo "::error::No changeset found. Run 'knope document-change'."
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
echo "✅ Found $CHANGESETS changeset(s)"
|
|
67
|
+
|
|
68
|
+
lint:
|
|
69
|
+
timeout-minutes: 60
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
steps:
|
|
72
|
+
- name: checkout repository
|
|
73
|
+
uses: actions/checkout@v4
|
|
74
|
+
|
|
75
|
+
- name: setup
|
|
76
|
+
uses: ./.github/actions/devenv
|
|
77
|
+
with:
|
|
78
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
79
|
+
|
|
80
|
+
- name: lint
|
|
81
|
+
run: lint:all
|
|
82
|
+
shell: devenv shell -c -- bash -e {0}
|
|
83
|
+
|
|
84
|
+
test:
|
|
85
|
+
timeout-minutes: 60
|
|
86
|
+
runs-on: ubuntu-latest
|
|
87
|
+
steps:
|
|
88
|
+
- name: checkout repository
|
|
89
|
+
uses: actions/checkout@v4
|
|
90
|
+
|
|
91
|
+
- name: setup
|
|
92
|
+
uses: ./.github/actions/devenv
|
|
93
|
+
with:
|
|
94
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
95
|
+
|
|
96
|
+
- name: run tests
|
|
97
|
+
run: test:all
|
|
98
|
+
shell: devenv shell -c -- bash -e {0}
|
|
99
|
+
|
|
100
|
+
build:
|
|
101
|
+
timeout-minutes: 60
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
needs: [commit-lint, changeset, lint, test]
|
|
104
|
+
if: ${{ !failure() && !cancelled() }}
|
|
105
|
+
steps:
|
|
106
|
+
- name: checkout repository
|
|
107
|
+
uses: actions/checkout@v4
|
|
108
|
+
|
|
109
|
+
- name: setup
|
|
110
|
+
uses: ./.github/actions/devenv
|
|
111
|
+
with:
|
|
112
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
113
|
+
|
|
114
|
+
- name: build default features
|
|
115
|
+
run: build:default
|
|
116
|
+
shell: devenv shell -c -- bash -e {0}
|
|
117
|
+
|
|
118
|
+
- name: build all features
|
|
119
|
+
run: build:all
|
|
120
|
+
shell: devenv shell -c -- bash -e {0}
|
|
121
|
+
|
|
122
|
+
security:
|
|
123
|
+
timeout-minutes: 30
|
|
124
|
+
runs-on: ubuntu-latest
|
|
125
|
+
steps:
|
|
126
|
+
- name: checkout repository
|
|
127
|
+
uses: actions/checkout@v4
|
|
128
|
+
|
|
129
|
+
- name: run cargo-deny
|
|
130
|
+
uses: EmbarkStudios/cargo-deny-action@v2
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: "coverage"
|
|
2
|
+
permissions:
|
|
3
|
+
contents: read
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
pull_request:
|
|
9
|
+
branches:
|
|
10
|
+
- main
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
coverage:
|
|
19
|
+
timeout-minutes: 90
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- name: checkout repository
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: setup
|
|
26
|
+
uses: ./.github/actions/devenv
|
|
27
|
+
with:
|
|
28
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
29
|
+
|
|
30
|
+
- name: generate coverage report
|
|
31
|
+
run: coverage:all
|
|
32
|
+
shell: devenv shell -c -- bash -e {0}
|
|
33
|
+
|
|
34
|
+
- name: upload lcov artifact
|
|
35
|
+
uses: actions/upload-artifact@v4
|
|
36
|
+
with:
|
|
37
|
+
name: coverage-lcov
|
|
38
|
+
path: target/coverage/lcov.info
|
|
39
|
+
if-no-files-found: error
|
|
40
|
+
|
|
41
|
+
- name: upload codecov report
|
|
42
|
+
uses: codecov/codecov-action@v5
|
|
43
|
+
with:
|
|
44
|
+
files: target/coverage/lcov.info
|
|
45
|
+
fail_ci_if_error: false
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: "docs-pages"
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- "docs/**"
|
|
9
|
+
- "readme.md"
|
|
10
|
+
- "devenv.nix"
|
|
11
|
+
- ".github/workflows/docs-pages.yml"
|
|
12
|
+
release:
|
|
13
|
+
types: [published]
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
pages: write
|
|
19
|
+
id-token: write
|
|
20
|
+
|
|
21
|
+
concurrency:
|
|
22
|
+
group: "pages"
|
|
23
|
+
cancel-in-progress: true
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
build:
|
|
27
|
+
if: github.repository == '__GITHUB_OWNER__/__GITHUB_REPO__'
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- name: checkout repository
|
|
31
|
+
uses: actions/checkout@v4
|
|
32
|
+
|
|
33
|
+
- name: setup
|
|
34
|
+
uses: ./.github/actions/devenv
|
|
35
|
+
with:
|
|
36
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
37
|
+
|
|
38
|
+
- name: configure github pages
|
|
39
|
+
uses: actions/configure-pages@v5
|
|
40
|
+
|
|
41
|
+
- name: build mdbook docs
|
|
42
|
+
run: docs:build
|
|
43
|
+
shell: devenv shell -c -- bash -e {0}
|
|
44
|
+
|
|
45
|
+
- name: upload pages artifact
|
|
46
|
+
uses: actions/upload-pages-artifact@v3
|
|
47
|
+
with:
|
|
48
|
+
path: docs/book
|
|
49
|
+
|
|
50
|
+
deploy:
|
|
51
|
+
if: github.repository == '__GITHUB_OWNER__/__GITHUB_REPO__'
|
|
52
|
+
needs: build
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
environment:
|
|
55
|
+
name: github-pages
|
|
56
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
57
|
+
steps:
|
|
58
|
+
- name: deploy to github pages
|
|
59
|
+
id: deployment
|
|
60
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: "release-preview"
|
|
2
|
+
permissions:
|
|
3
|
+
contents: read
|
|
4
|
+
on:
|
|
5
|
+
pull_request:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
preview:
|
|
16
|
+
timeout-minutes: 20
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- name: checkout repository
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 0
|
|
23
|
+
|
|
24
|
+
- name: setup
|
|
25
|
+
uses: ./.github/actions/devenv
|
|
26
|
+
with:
|
|
27
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
28
|
+
|
|
29
|
+
- name: preview release
|
|
30
|
+
run: |
|
|
31
|
+
echo "## Release Preview" >> "$GITHUB_STEP_SUMMARY"
|
|
32
|
+
echo "" >> "$GITHUB_STEP_SUMMARY"
|
|
33
|
+
|
|
34
|
+
if ls .changeset/*.md 1>/dev/null 2>&1; then
|
|
35
|
+
echo "### Changesets" >> "$GITHUB_STEP_SUMMARY"
|
|
36
|
+
echo '```markdown' >> "$GITHUB_STEP_SUMMARY"
|
|
37
|
+
for f in .changeset/*.md; do
|
|
38
|
+
echo "--- $f ---" >> "$GITHUB_STEP_SUMMARY"
|
|
39
|
+
cat "$f" >> "$GITHUB_STEP_SUMMARY"
|
|
40
|
+
echo "" >> "$GITHUB_STEP_SUMMARY"
|
|
41
|
+
done
|
|
42
|
+
echo '```' >> "$GITHUB_STEP_SUMMARY"
|
|
43
|
+
else
|
|
44
|
+
echo "No changesets found in .changeset/." >> "$GITHUB_STEP_SUMMARY"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
echo "" >> "$GITHUB_STEP_SUMMARY"
|
|
48
|
+
echo "### knope release --dry-run" >> "$GITHUB_STEP_SUMMARY"
|
|
49
|
+
echo '```' >> "$GITHUB_STEP_SUMMARY"
|
|
50
|
+
knope release --dry-run 2>&1 | tee -a "$GITHUB_STEP_SUMMARY" || true
|
|
51
|
+
echo '```' >> "$GITHUB_STEP_SUMMARY"
|
|
52
|
+
shell: devenv shell -- bash -e {0}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
name: "release"
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
tag:
|
|
9
|
+
description: "Release tag (e.g. v0.3.0). Must start with 'v'."
|
|
10
|
+
required: true
|
|
11
|
+
type: string
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}-${{ inputs.tag || github.event.release.tag_name }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
upload_assets:
|
|
19
|
+
env:
|
|
20
|
+
CARGO_PROFILE_RELEASE_LTO: true
|
|
21
|
+
CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 1
|
|
22
|
+
CARGO_PROFILE_RELEASE_STRIP: symbols
|
|
23
|
+
RELEASE_TAG: ${{ inputs.tag || github.event.release.tag_name }}
|
|
24
|
+
permissions:
|
|
25
|
+
contents: write
|
|
26
|
+
if: github.repository == '__GITHUB_OWNER__/__GITHUB_REPO__' && startsWith(inputs.tag || github.event.release.tag_name, 'v')
|
|
27
|
+
strategy:
|
|
28
|
+
fail-fast: false
|
|
29
|
+
matrix:
|
|
30
|
+
include:
|
|
31
|
+
- target: aarch64-unknown-linux-gnu
|
|
32
|
+
os: ubuntu-latest
|
|
33
|
+
- target: aarch64-unknown-linux-musl
|
|
34
|
+
os: ubuntu-latest
|
|
35
|
+
- target: aarch64-apple-darwin
|
|
36
|
+
os: macos-14
|
|
37
|
+
- target: x86_64-unknown-linux-gnu
|
|
38
|
+
os: ubuntu-latest
|
|
39
|
+
- target: x86_64-unknown-linux-musl
|
|
40
|
+
os: ubuntu-latest
|
|
41
|
+
- target: x86_64-apple-darwin
|
|
42
|
+
os: macos-latest
|
|
43
|
+
- target: x86_64-pc-windows-msvc
|
|
44
|
+
os: windows-latest
|
|
45
|
+
- target: aarch64-pc-windows-msvc
|
|
46
|
+
os: windows-latest
|
|
47
|
+
runs-on: ${{ matrix.os }}
|
|
48
|
+
timeout-minutes: 60
|
|
49
|
+
steps:
|
|
50
|
+
- name: checkout
|
|
51
|
+
uses: actions/checkout@v4
|
|
52
|
+
with:
|
|
53
|
+
ref: ${{ env.RELEASE_TAG }}
|
|
54
|
+
|
|
55
|
+
- name: install rust toolchain
|
|
56
|
+
uses: dtolnay/rust-toolchain@stable
|
|
57
|
+
|
|
58
|
+
- name: setup cross toolchain
|
|
59
|
+
uses: taiki-e/setup-cross-toolchain-action@v1
|
|
60
|
+
with:
|
|
61
|
+
target: ${{ matrix.target }}
|
|
62
|
+
if: startsWith(matrix.os, 'ubuntu') && !contains(matrix.target, '-musl')
|
|
63
|
+
|
|
64
|
+
- name: install cross
|
|
65
|
+
uses: taiki-e/install-action@v2
|
|
66
|
+
with:
|
|
67
|
+
tool: cross
|
|
68
|
+
if: contains(matrix.target, '-musl')
|
|
69
|
+
|
|
70
|
+
- name: set static crt linkage
|
|
71
|
+
shell: bash
|
|
72
|
+
run: echo "RUSTFLAGS=${RUSTFLAGS} -C target-feature=+crt-static" >> "${GITHUB_ENV}"
|
|
73
|
+
if: endsWith(matrix.target, 'windows-msvc')
|
|
74
|
+
|
|
75
|
+
- name: upload binaries
|
|
76
|
+
uses: taiki-e/upload-rust-binary-action@v1
|
|
77
|
+
with:
|
|
78
|
+
bin: __PROJECT_NAME__
|
|
79
|
+
manifest-path: crates/__CLI_CRATE__/Cargo.toml
|
|
80
|
+
package: __CLI_CRATE__
|
|
81
|
+
ref: refs/tags/${{ env.RELEASE_TAG }}
|
|
82
|
+
archive: $bin-$target-$tag
|
|
83
|
+
target: ${{ matrix.target }}
|
|
84
|
+
tar: all
|
|
85
|
+
zip: windows
|
|
86
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
87
|
+
checksum: sha256,sha512
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: "semver"
|
|
2
|
+
permissions:
|
|
3
|
+
contents: read
|
|
4
|
+
on:
|
|
5
|
+
pull_request:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
semver-checks:
|
|
15
|
+
timeout-minutes: 30
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- name: checkout repository
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
|
|
23
|
+
- name: setup
|
|
24
|
+
uses: ./.github/actions/devenv
|
|
25
|
+
with:
|
|
26
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
+
|
|
28
|
+
- name: run semver-checks
|
|
29
|
+
id: semver
|
|
30
|
+
continue-on-error: true
|
|
31
|
+
run: cargo semver-checks check-release --workspace
|
|
32
|
+
shell: devenv shell -c -- bash -e {0}
|
|
33
|
+
|
|
34
|
+
- name: evaluate semver results
|
|
35
|
+
if: steps.semver.outcome == 'failure'
|
|
36
|
+
env:
|
|
37
|
+
PR_TITLE: ${{ github.event.pull_request.title }}
|
|
38
|
+
run: |
|
|
39
|
+
echo "::warning::semver-checks detected breaking changes"
|
|
40
|
+
|
|
41
|
+
title_acknowledged=false
|
|
42
|
+
if echo "$PR_TITLE" | grep -qE '^[a-zA-Z]+(\(.+\))?!:'; then
|
|
43
|
+
title_acknowledged=true
|
|
44
|
+
echo "PR title contains '!' — breaking change acknowledged via title"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
changeset_acknowledged=false
|
|
48
|
+
if ls .changeset/*.md 1>/dev/null 2>&1; then
|
|
49
|
+
if grep -lE '^[a-zA-Z_]+: major$' .changeset/*.md 1>/dev/null 2>&1; then
|
|
50
|
+
changeset_acknowledged=true
|
|
51
|
+
echo "Found major changeset — breaking change acknowledged via changeset"
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
if [ "$title_acknowledged" = true ] || [ "$changeset_acknowledged" = true ]; then
|
|
56
|
+
echo "::notice::Breaking changes are acknowledged."
|
|
57
|
+
exit 0
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
echo "::error::Breaking changes detected but not acknowledged."
|
|
61
|
+
echo "Add '!' to PR title or create a major changeset via 'knope document-change'."
|
|
62
|
+
exit 1
|
|
63
|
+
shell: bash
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[workspace]
|
|
2
|
+
resolver = "2"
|
|
3
|
+
members = ["crates/__CORE_CRATE__", "crates/__CLI_CRATE__"]
|
|
4
|
+
|
|
5
|
+
[workspace.package]
|
|
6
|
+
version = "0.1.0"
|
|
7
|
+
authors = ["__GITHUB_OWNER__"]
|
|
8
|
+
edition = "2024"
|
|
9
|
+
license = "MIT"
|
|
10
|
+
readme = "readme.md"
|
|
11
|
+
repository = "https://github.com/__GITHUB_OWNER__/__GITHUB_REPO__"
|
|
12
|
+
homepage = "https://github.com/__GITHUB_OWNER__/__GITHUB_REPO__"
|
|
13
|
+
rust-version = "1.86.0"
|
|
14
|
+
description = "__DESCRIPTION__"
|
|
15
|
+
|
|
16
|
+
[workspace.dependencies]
|
|
17
|
+
clap = { default-features = false, version = "^4", features = ["derive", "std"] }
|
|
18
|
+
thiserror = { default-features = false, version = "^2" }
|
|
19
|
+
__CORE_CRATE__ = { path = "crates/__CORE_CRATE__", version = "0.1.0" }
|
|
20
|
+
|
|
21
|
+
[workspace.metadata.bin]
|
|
22
|
+
cargo-deny = { version = "0.19.0" }
|
|
23
|
+
cargo-llvm-cov = { version = "0.8.4" }
|
|
24
|
+
cargo-nextest = { version = "0.9.129" }
|
|
25
|
+
cargo-semver-checks = { version = "0.46.0" }
|
|
26
|
+
cargo-workspaces = { version = "0.4.2" }
|
|
27
|
+
knope = { version = "0.22.3", bins = ["knope"] }
|
|
28
|
+
|
|
29
|
+
[workspace.lints.rust]
|
|
30
|
+
rust_2021_compatibility = { level = "warn", priority = -1 }
|
|
31
|
+
rust_2024_compatibility = { level = "warn", priority = -1 }
|
|
32
|
+
unsafe_code = "deny"
|
|
33
|
+
unstable_features = "deny"
|
|
34
|
+
unused_extern_crates = "warn"
|
|
35
|
+
unused_import_braces = "warn"
|
|
36
|
+
unused_lifetimes = "warn"
|
|
37
|
+
unused_macro_rules = "warn"
|
|
38
|
+
unused_qualifications = "warn"
|
|
39
|
+
variant_size_differences = "warn"
|
|
40
|
+
edition_2024_expr_fragment_specifier = "allow"
|
|
41
|
+
|
|
42
|
+
[workspace.lints.clippy]
|
|
43
|
+
complexity = { level = "warn", priority = -1 }
|
|
44
|
+
correctness = { level = "deny", priority = -1 }
|
|
45
|
+
pedantic = { level = "warn", priority = -1 }
|
|
46
|
+
perf = { level = "warn", priority = -1 }
|
|
47
|
+
style = { level = "warn", priority = -1 }
|
|
48
|
+
suspicious = { level = "warn", priority = -1 }
|
|
49
|
+
|
|
50
|
+
blocks_in_conditions = "allow"
|
|
51
|
+
cargo_common_metadata = "allow"
|
|
52
|
+
cast_possible_truncation = "allow"
|
|
53
|
+
cast_possible_wrap = "allow"
|
|
54
|
+
cast_precision_loss = "allow"
|
|
55
|
+
cast_sign_loss = "allow"
|
|
56
|
+
items_after_statements = "allow"
|
|
57
|
+
missing_errors_doc = "allow"
|
|
58
|
+
missing_panics_doc = "allow"
|
|
59
|
+
module_name_repetitions = "allow"
|
|
60
|
+
must_use_candidate = "allow"
|
|
61
|
+
no_effect_underscore_binding = "allow"
|
|
62
|
+
too_many_lines = "allow"
|
|
63
|
+
wildcard_dependencies = "deny"
|
|
64
|
+
wildcard_imports = "allow"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
msrv = "1.86"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "__CLI_CRATE__"
|
|
3
|
+
version.workspace = true
|
|
4
|
+
edition.workspace = true
|
|
5
|
+
license.workspace = true
|
|
6
|
+
readme.workspace = true
|
|
7
|
+
repository.workspace = true
|
|
8
|
+
rust-version.workspace = true
|
|
9
|
+
description = "CLI for __PROJECT_NAME__"
|
|
10
|
+
|
|
11
|
+
[[bin]]
|
|
12
|
+
name = "__PROJECT_NAME__"
|
|
13
|
+
path = "src/main.rs"
|
|
14
|
+
|
|
15
|
+
[lints]
|
|
16
|
+
workspace = true
|
|
17
|
+
|
|
18
|
+
[dependencies]
|
|
19
|
+
clap.workspace = true
|
|
20
|
+
__CORE_CRATE__.workspace = true
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
use clap::Parser;
|
|
2
|
+
|
|
3
|
+
#[derive(Debug, Parser)]
|
|
4
|
+
#[command(name = "__PROJECT_NAME__")]
|
|
5
|
+
#[command(about = "__DESCRIPTION__")]
|
|
6
|
+
struct Args {
|
|
7
|
+
/// Optional name to greet.
|
|
8
|
+
#[arg(short, long, default_value = "world")]
|
|
9
|
+
name: String,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
fn main() {
|
|
13
|
+
let args = Args::parse();
|
|
14
|
+
match __CORE_CRATE__::greet(&args.name) {
|
|
15
|
+
Ok(message) => println!("{message}"),
|
|
16
|
+
Err(error) => {
|
|
17
|
+
eprintln!("error: {error}");
|
|
18
|
+
std::process::exit(1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "__CORE_CRATE__"
|
|
3
|
+
version.workspace = true
|
|
4
|
+
edition.workspace = true
|
|
5
|
+
license.workspace = true
|
|
6
|
+
readme.workspace = true
|
|
7
|
+
repository.workspace = true
|
|
8
|
+
rust-version.workspace = true
|
|
9
|
+
description = "Core library for __PROJECT_NAME__"
|
|
10
|
+
|
|
11
|
+
[lints]
|
|
12
|
+
workspace = true
|
|
13
|
+
|
|
14
|
+
[dependencies]
|
|
15
|
+
thiserror.workspace = true
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
use thiserror::Error;
|
|
2
|
+
|
|
3
|
+
#[derive(Debug, Error)]
|
|
4
|
+
pub enum CoreError {
|
|
5
|
+
#[error("name cannot be empty")]
|
|
6
|
+
EmptyName,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
pub fn greet(name: &str) -> Result<String, CoreError> {
|
|
10
|
+
if name.trim().is_empty() {
|
|
11
|
+
return Err(CoreError::EmptyName);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Ok(format!("Hello, {name}!"))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#[cfg(test)]
|
|
18
|
+
mod tests {
|
|
19
|
+
use super::greet;
|
|
20
|
+
|
|
21
|
+
#[test]
|
|
22
|
+
fn greets_with_name() {
|
|
23
|
+
let result = greet("world");
|
|
24
|
+
assert_eq!(result.as_deref(), Ok("Hello, world!"));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
#[test]
|
|
28
|
+
fn rejects_empty_name() {
|
|
29
|
+
let result = greet(" ");
|
|
30
|
+
assert!(result.is_err());
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[graph]
|
|
2
|
+
all-features = true
|
|
3
|
+
|
|
4
|
+
[advisories]
|
|
5
|
+
version = 2
|
|
6
|
+
yanked = "deny"
|
|
7
|
+
|
|
8
|
+
[licenses]
|
|
9
|
+
version = 2
|
|
10
|
+
allow = ["MIT", "Apache-2.0", "BSD-3-Clause", "ISC", "Unicode-3.0"]
|
|
11
|
+
confidence-threshold = 0.93
|
|
12
|
+
|
|
13
|
+
[bans]
|
|
14
|
+
multiple-versions = "warn"
|
|
15
|
+
|
|
16
|
+
[sources]
|
|
17
|
+
unknown-registry = "deny"
|
|
18
|
+
unknown-git = "warn"
|