Skip to content

Commit 1c896dc

Browse files
Enhance CI workflows: add release validation and asset upload steps (#10)
1 parent 16bdad7 commit 1c896dc

File tree

2 files changed

+267
-34
lines changed

2 files changed

+267
-34
lines changed

.github/workflows/ci.yml

Lines changed: 193 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,79 +9,184 @@ on:
99
- main
1010
merge_group:
1111
types: [checks_requested]
12+
release:
13+
types: [published]
1214

1315
permissions:
14-
contents: read
16+
contents: write
1517
pull-requests: write
1618
checks: write
1719

1820
jobs:
19-
linting-and-formatting:
20-
name: "Linting and Formatting"
21-
runs-on: "ubuntu-latest"
21+
# =============================================================================
22+
# Linting and formatting checks
23+
# =============================================================================
24+
25+
ruff-format:
26+
name: Ruff format
27+
runs-on: ubuntu-latest
2228
env:
23-
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
2430
steps:
2531
- name: Checkout the repository
2632
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
27-
with:
28-
fetch-depth: 0
2933

30-
# Install job dependencies
3134
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
32-
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
33-
- uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1.5.0
34-
with:
35-
reviewdog_version: v0.20.3
3635

3736
- name: Install python dependencies
3837
run: uv sync --locked --all-extras --dev
3938

40-
- name: Format
41-
if: ${{ !cancelled() }}
39+
- name: Setup reviewdog
40+
if: github.event_name == 'pull_request'
41+
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1.5.0
42+
with:
43+
reviewdog_version: v0.20.3
44+
45+
- name: Ruff format (reviewdog)
46+
if: github.event_name == 'pull_request'
4247
run: |
4348
uv run ruff format --diff \
4449
| reviewdog -f=diff -name="ruff format" -reporter=github-pr-review -filter-mode=nofilter -fail-level=any
4550
46-
- name: Lint
47-
if: ${{ !cancelled() }}
51+
- name: Ruff format (check)
52+
if: github.event_name != 'pull_request'
53+
run: uv run ruff format --check
54+
55+
ruff-lint:
56+
name: Ruff lint
57+
runs-on: ubuntu-latest
58+
env:
59+
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
60+
steps:
61+
- name: Checkout the repository
62+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
63+
64+
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
65+
66+
- name: Install python dependencies
67+
run: uv sync --locked --all-extras --dev
68+
69+
- name: Setup reviewdog
70+
if: github.event_name == 'pull_request'
71+
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1.5.0
72+
with:
73+
reviewdog_version: v0.20.3
74+
75+
- name: Ruff lint (reviewdog)
76+
if: github.event_name == 'pull_request'
4877
run: |
4978
uv run ruff check --output-format rdjson \
5079
| reviewdog -f=rdjson -name="ruff lint" -reporter=github-pr-review -filter-mode=nofilter -fail-level=any
5180
52-
- name: Type Check
53-
if: ${{ !cancelled() }}
81+
- name: Ruff lint (check)
82+
if: github.event_name != 'pull_request'
83+
run: uv run ruff check
84+
85+
pyright:
86+
name: Pyright
87+
runs-on: ubuntu-latest
88+
env:
89+
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
90+
steps:
91+
- name: Checkout the repository
92+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
93+
94+
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
95+
96+
- name: Install python dependencies
97+
run: uv sync --locked --all-extras --dev
98+
99+
- name: Setup reviewdog
100+
if: github.event_name == 'pull_request'
101+
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1.5.0
102+
with:
103+
reviewdog_version: v0.20.3
104+
105+
- name: Pyright (reviewdog)
106+
if: github.event_name == 'pull_request'
54107
run: |
55108
uv run pyright \
56109
| reviewdog -efm="%f:%l:%c - %t%*[^:]: %m" -name="pyright type check" -reporter=github-pr-review -filter-mode=nofilter -fail-level=any
57110
58-
- name: Prettier
59-
if: ${{ !cancelled() }}
111+
- name: Pyright (check)
112+
if: github.event_name != 'pull_request'
113+
run: uv run pyright
114+
115+
prettier:
116+
name: Prettier
117+
runs-on: ubuntu-latest
118+
env:
119+
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
120+
steps:
121+
- name: Checkout the repository
122+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
123+
124+
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
125+
126+
- name: Setup reviewdog
127+
if: github.event_name == 'pull_request'
128+
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1.5.0
129+
with:
130+
reviewdog_version: v0.20.3
131+
132+
- name: Prettier (reviewdog)
133+
if: github.event_name == 'pull_request'
60134
run: |
61-
git clean -d -f -x
62135
npm ci
63136
npx --yes prettier@3 --write .
64137
git diff \
65138
| reviewdog -f=diff -name="prettier" -reporter=github-pr-review -filter-mode=nofilter -fail-level=any
66139
67-
- name: Markdown Format
68-
if: ${{ !cancelled() }}
140+
- name: Prettier (check)
141+
if: github.event_name != 'pull_request'
142+
run: |
143+
npm ci
144+
npx --yes prettier@3 --check .
145+
146+
mdformat:
147+
name: Markdown format
148+
runs-on: ubuntu-latest
149+
env:
150+
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
151+
steps:
152+
- name: Checkout the repository
153+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
154+
155+
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
156+
157+
- name: Install python dependencies
158+
run: uv sync --locked --all-extras --dev
159+
160+
- name: Setup reviewdog
161+
if: github.event_name == 'pull_request'
162+
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1.5.0
163+
with:
164+
reviewdog_version: v0.20.3
165+
166+
- name: Markdown format (reviewdog)
167+
if: github.event_name == 'pull_request'
69168
run: |
70-
git clean -d -f -x
71169
uv run mdformat $(git ls-files '*.md' '*.mdx')
72170
git diff \
73171
| reviewdog -f=diff -name="mdformat" -reporter=github-pr-review -filter-mode=nofilter -fail-level=any
74172
173+
- name: Markdown format (check)
174+
if: github.event_name != 'pull_request'
175+
run: uv run mdformat --check $(git ls-files '*.md' '*.mdx')
176+
177+
# =============================================================================
178+
# Tests
179+
# =============================================================================
180+
75181
test:
76-
name: "Run Tests"
77-
runs-on: "ubuntu-latest"
182+
name: Tests
183+
runs-on: ubuntu-latest
78184
steps:
79185
- name: Checkout the repository
80186
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
81187
with:
82188
fetch-depth: 0
83189

84-
# Install job dependencies
85190
- name: Install uv
86191
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
87192

@@ -92,21 +197,25 @@ jobs:
92197
run: uv run pytest --cov=custom_components/hafo --cov-branch --cov-report=xml --junitxml=junit.xml -o junit_family=legacy
93198

94199
- name: Upload test results to Codecov
95-
if: ${{ !cancelled() }}
200+
if: ${{ github.event_name != 'release' && !cancelled() }}
96201
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
97202
with:
98203
report_type: test_results
99204
token: ${{ secrets.CODECOV_TOKEN }}
100205

101206
- name: Upload coverage to Codecov
102-
if: ${{ !cancelled() }}
207+
if: ${{ github.event_name != 'release' && !cancelled() }}
103208
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
104209
with:
105210
fail_ci_if_error: true
106211
token: ${{ secrets.CODECOV_TOKEN }}
107212

108-
hassfest: # https://developers.home-assistant.io/blog/2020/04/16/hassfest
109-
name: Hassfest validation
213+
# =============================================================================
214+
# Validation checks
215+
# =============================================================================
216+
217+
hassfest:
218+
name: Hassfest
110219
runs-on: ubuntu-latest
111220
steps:
112221
- name: Checkout the repository
@@ -116,7 +225,7 @@ jobs:
116225
uses: home-assistant/actions/hassfest@87c064c607f3c5cc673a24258d0c98d23033bfc3 # master
117226

118227
version-check:
119-
name: Version consistency check
228+
name: Version consistency
120229
runs-on: ubuntu-latest
121230
steps:
122231
- name: Checkout the repository
@@ -139,8 +248,8 @@ jobs:
139248
echo "pyproject.toml=$PYPROJECT hacs.json=$HACS"
140249
[[ "$PYPROJECT" == "$HACS" ]]
141250
142-
hacs: # https://github.com/hacs/action
143-
name: HACS validation
251+
hacs:
252+
name: HACS
144253
runs-on: ubuntu-latest
145254
steps:
146255
- name: Run HACS validation
@@ -149,3 +258,53 @@ jobs:
149258
category: integration
150259
# Remove this 'ignore' key when you have added brand images for your integration to https://github.com/home-assistant/brands
151260
ignore: brands
261+
262+
docs:
263+
name: Documentation
264+
runs-on: ubuntu-latest
265+
steps:
266+
- name: Checkout repository
267+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
268+
with:
269+
fetch-depth: 0
270+
271+
- name: Install uv
272+
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
273+
274+
- name: Install dependencies
275+
run: uv sync
276+
277+
- name: Build documentation
278+
run: uv run mkdocs build --strict
279+
280+
# =============================================================================
281+
# CI passed (single required check)
282+
# =============================================================================
283+
284+
ci-passed:
285+
name: CI passed
286+
if: always()
287+
needs:
288+
- ruff-format
289+
- ruff-lint
290+
- pyright
291+
- prettier
292+
- mdformat
293+
- test
294+
- hassfest
295+
- version-check
296+
- hacs
297+
- docs
298+
runs-on: ubuntu-latest
299+
steps:
300+
- name: Check all jobs passed
301+
run: |
302+
if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then
303+
echo "::error::One or more required jobs failed"
304+
exit 1
305+
fi
306+
if [[ "${{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
307+
echo "::error::One or more required jobs were cancelled"
308+
exit 1
309+
fi
310+
echo "All required jobs passed!"

.github/workflows/release.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: Release
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
validate-release:
12+
name: Validate release version
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout the repository
16+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
17+
18+
- name: Install uv
19+
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
20+
21+
- name: Extract and validate version from release tag
22+
run: |
23+
TAG="${{ github.event.release.tag_name }}"
24+
VERSION="${TAG#v}"
25+
echo "Tag: $TAG"
26+
echo "Version: $VERSION"
27+
28+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
29+
echo "::error::Release tag '$TAG' does not match semantic versioning format (vX.Y.Z)"
30+
exit 1
31+
fi
32+
33+
- name: Check pyproject.toml version matches tag
34+
run: |
35+
TAG="${{ github.event.release.tag_name }}"
36+
TAG_VERSION="${TAG#v}"
37+
PYPROJECT_VERSION=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
38+
echo "Tag version: $TAG_VERSION"
39+
echo "pyproject.toml version: $PYPROJECT_VERSION"
40+
if [[ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]]; then
41+
echo "::error::Tag version ($TAG_VERSION) does not match pyproject.toml version ($PYPROJECT_VERSION)"
42+
exit 1
43+
fi
44+
45+
- name: Check manifest.json version matches tag
46+
run: |
47+
TAG="${{ github.event.release.tag_name }}"
48+
TAG_VERSION="${TAG#v}"
49+
MANIFEST_VERSION=$(jq -r '.version' custom_components/hafo/manifest.json)
50+
echo "Tag version: $TAG_VERSION"
51+
echo "manifest.json version: $MANIFEST_VERSION"
52+
if [[ "$TAG_VERSION" != "$MANIFEST_VERSION" ]]; then
53+
echo "::error::Tag version ($TAG_VERSION) does not match manifest.json version ($MANIFEST_VERSION)"
54+
exit 1
55+
fi
56+
57+
upload-assets:
58+
name: Upload release assets
59+
needs: validate-release
60+
runs-on: ubuntu-latest
61+
steps:
62+
- name: Checkout the repository
63+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
64+
65+
- name: Create release package
66+
run: |
67+
cd custom_components
68+
zip -r ../hafo.zip hafo
69+
70+
- name: Upload release assets
71+
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2
72+
with:
73+
files: |
74+
hafo.zip

0 commit comments

Comments
 (0)