Skip to content

Commit 23d1253

Browse files
authored
uv/taskfile migration (#13)
1 parent 2f76285 commit 23d1253

File tree

19 files changed

+850
-720
lines changed

19 files changed

+850
-720
lines changed

.github/workflows/ci.yml

Lines changed: 56 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -25,50 +25,47 @@ jobs:
2525
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
2626
- name: Check out repository code
2727
uses: actions/checkout@v3
28-
- name: Set up Python ${{ matrix.python-version }}
29-
uses: actions/setup-python@v4
28+
- name: Install Task
29+
uses: arduino/setup-task@v2
3030
with:
31-
python-version: ${{ matrix.python-version }}
32-
- name: Cache deps install
33-
id: cache-deps
34-
uses: actions/cache@v3
31+
version: 3.x
32+
repo-token: ${{ secrets.GITHUB_TOKEN }}
33+
- name: Install the latest version of uv
34+
uses: astral-sh/setup-uv@v5
3535
with:
36-
path: |
37-
${{ env.POETRY_HOME }}
38-
${{ env.POETRY_CACHE }}
39-
key: cachepoetry-${{ hashFiles('poetry.lock', '.github/workflows/**') }}-${{ matrix.python-version }}
40-
- name: Install poetry
41-
if: steps.cache-deps.outputs.cache-hit != 'true'
42-
run: |
43-
python3 -m venv $POETRY_HOME
44-
$POETRY_HOME/bin/pip install poetry==$POETRY_VERSION
45-
- name: Fix github path
46-
run: |
47-
echo "$POETRY_HOME/bin" >> "$GITHUB_PATH"
48-
- name: Configure poetry
49-
run: |
50-
poetry config virtualenvs.create true
51-
poetry config virtualenvs.in-project false
52-
poetry config cache-dir $POETRY_CACHE
53-
poetry config virtualenvs.path $POETRY_CACHE/venv
54-
- name: Install requirements
55-
if: steps.cache-deps.outputs.cache-hit != 'true'
36+
version: "latest"
37+
python-version: ${{ matrix.python-version }}
38+
- name: Install
5639
run: |
57-
poetry install
40+
task install
5841
- name: Run lint
5942
run: |
60-
poetry run make FIX=0 lint
61-
- name: Run tests / coverage
43+
if [ "${{ matrix.python-version }}" = "3.8" ]; then
44+
# As we have mypy issues with 3.8 => let's skip
45+
export LINT_MYPY=0
46+
fi
47+
task lint
48+
env:
49+
FIX: 0
50+
- name: Run tests
6251
run: |
63-
poetry run make test
52+
task test
6453
- name: Run doc
6554
if: matrix.python-version == '3.12'
6655
run: |
67-
poetry run make doc
56+
task doc
6857
- name: Check modified files
6958
if: matrix.python-version == '3.12'
7059
run: |
71-
git diff --exit-code
60+
task no-dirty
61+
- name: Clean
62+
if: matrix.python-version == '3.12'
63+
run: |
64+
task clean
65+
- name: Check modified files (after clean)
66+
if: matrix.python-version == '3.12'
67+
run: |
68+
task no-dirty
7269
7370
publish_pypi:
7471
runs-on: ubuntu-latest
@@ -77,53 +74,53 @@ jobs:
7774
steps:
7875
- name: Check out repository code
7976
uses: actions/checkout@v3
80-
- name: Set up Python 3.8
81-
uses: actions/setup-python@v4
77+
- name: Install Task
78+
uses: arduino/setup-task@v2
8279
with:
83-
python-version: 3.8
84-
- name: Install poetry
85-
run: |
86-
python3 -m venv $POETRY_HOME
87-
$POETRY_HOME/bin/pip install poetry==$POETRY_VERSION
88-
- name: Fix github path
89-
run: |
90-
echo "$POETRY_HOME/bin" >> "$GITHUB_PATH"
91-
- name: Install requirements
80+
version: 3.x
81+
repo-token: ${{ secrets.GITHUB_TOKEN }}
82+
- name: Install the latest version of uv
83+
uses: astral-sh/setup-uv@v5
84+
with:
85+
version: "latest"
86+
python-version: 3.12
87+
- name: Install
9288
run: |
93-
poetry install
89+
task install
9490
- name: Override BASEURL in README.md
9591
env:
9692
BASEURL: https://github.com/fabien-marty/jinja-tree/blob/main/
9793
run: |
98-
poetry run jinja-tree .
94+
task doc
9995
- name: Publish on Pypi
10096
run: |
101-
poetry config pypi-token.pypi "${{ secrets.PYPI_TOKEN }}"
10297
VERSION=$(echo "${{ github.event.release.tag_name }}" | sed -e 's/^v//')
103-
poetry version "${VERSION}"
104-
poetry build
105-
poetry publish
98+
echo "VERSION: $VERSION"
99+
uvx --from=toml-cli toml set --toml-path=pyproject.toml project.version "$VERSION"
100+
task publish
101+
env:
102+
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
106103

107104
test_docker:
108105
runs-on: ubuntu-latest
109106
needs: lint_and_test
110107
if: github.event_name != 'release'
111-
env:
112-
REGISTRY: ghcr.io
113-
IMAGE_NAME: ${{ github.repository }}
114-
permissions:
115-
contents: read
116-
packages: write
108+
#env:
109+
# REGISTRY: ghcr.io
110+
# IMAGE_NAME: ${{ github.repository }}
111+
#permissions:
112+
# contents: read
113+
# packages: write
117114
steps:
118115
- name: Check out repository code
119116
uses: actions/checkout@v4
120-
- name: Build docker
121-
run: |
122-
make docker
117+
- name: Build and push Docker image
118+
uses: docker/build-push-action@v5
119+
with:
120+
push: false
123121

124122
publish_docker:
125123
runs-on: ubuntu-latest
126-
needs: publish_pypi
127124
if: github.event_name == 'release' && github.event.action == 'created'
128125
env:
129126
REGISTRY: ghcr.io
@@ -148,7 +145,6 @@ jobs:
148145
- name: Build and push Docker image
149146
uses: docker/build-push-action@v5
150147
with:
151-
context: docker
152148
push: true
153149
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
154150
labels: ${{ steps.meta.outputs.labels }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,4 @@ cython_debug/
159159
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
160160
#.idea/
161161
.vscode/
162+
.tmp/

.task/checksum/uv-lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7d5d8728f1c41f9ef46ce7da4b2e06d7

.task/checksum/uv-sync

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
8135260813d08073fd8fc730744e95f7
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
8135260813d08073fd8fc730744e95f7

.task/taskfiles/Taskfile-misc.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: '3'
2+
3+
tasks:
4+
5+
no-dirty:
6+
desc: "Check that the repository is clean"
7+
silent: true
8+
cmds:
9+
- |
10+
if test -n "$(git status --porcelain)"; then
11+
echo "ERROR: the repository is dirty"
12+
git status
13+
git diff
14+
exit 1
15+
fi

.task/taskfiles/Taskfile-uv.yml

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
version: '3'
2+
3+
vars:
4+
UV_EXTERNAL:
5+
sh: "( uv --version >/dev/null 2>&1 && echo 1 ) || echo 0"
6+
UV_DIR:
7+
sh: "( uv --version >/dev/null 2>&1 && dirname $(which uv) ) || echo {{.ROOT_DIR}}/.tmp/bin"
8+
UV: "{{.UV_DIR}}/uv"
9+
UVX: "{{.UV_DIR}}/uvx"
10+
VENV: "{{.ROOT_DIR}}/.venv"
11+
12+
DEFAULT_UV_SYNC_OPTS: "--frozen"
13+
UV_SYNC_OPTS: "{{.UV_SYNC_OPTS | default .DEFAULT_UV_SYNC_OPTS}}"
14+
15+
# MYPY
16+
DEFAULT_LINT_MYPY: 1
17+
LINT_MYPY: "{{.LINT_MYPY | default .DEFAULT_LINT_MYPY}}"
18+
DEFAULT_MYPY_OPTS: "--check-untyped-defs"
19+
MYPY_OPTS: "{{.MYPY_OPTS | default .DEFAULT_MYPY_OPTS}}"
20+
DEFAULT_MYPY_ARGS: "."
21+
MYPY_ARGS: "{{.MYPY_ARGS | default .DEFAULT_MYPY_ARGS}}"
22+
MYPY: "{{.UV}} run mypy"
23+
24+
# RUFF
25+
DEFAULT_LINT_RUFF: 1
26+
LINT_RUFF: "{{.LINT_RUFF | default .DEFAULT_LINT_RUFF}}"
27+
DEFAULT_FIX: 1
28+
FIX: "{{.FIX | default .DEFAULT_FIX}}"
29+
DEFAULT_RUFF_OPTS: ""
30+
RUFF_OPTS: "{{.RUFF_OPTS | default .DEFAULT_RUFF_OPTS}}"
31+
DEFAULT_RUFF_ARGS: "."
32+
RUFF_ARGS: "{{.RUFF_ARGS | default .DEFAULT_RUFF_ARGS}}"
33+
RUFF: "{{.UV}} run ruff"
34+
35+
# PYTEST
36+
DEFAULT_TEST_PYTEST: 1
37+
TEST_PYTEST: "{{.TEST_PYTEST | default .DEFAULT_TEST_PYTEST}}"
38+
DEFAULT_COVERAGE: 0
39+
COVERAGE: "{{.COVERAGE | default .DEFAULT_COVERAGE}}"
40+
DEFAULT_PYTEST_COVERAGE_OPTS: "--no-cov-on-fail --cov=jinja_tree --cov-report=term --cov-report=html --cov-report=xml"
41+
PYTEST_COVERAGE_OPTS: "{{.PYTEST_COVERAGE_OPTS | default .DEFAULT_PYTEST_COVERAGE_OPTS}}"
42+
DEFAULT_PYTEST_ARGS: "tests"
43+
PYTEST_ARGS: "{{.PYTEST_ARGS | default .DEFAULT_PYTEST_ARGS}}"
44+
PYTEST: "{{.UV}} run pytest"
45+
46+
tasks:
47+
48+
install:
49+
desc: "(advanced) Install uv (if not already installed) in a local temporary directory"
50+
status:
51+
- "test '{{.UV_EXTERNAL}}' = '1'"
52+
env:
53+
UV_NO_MODIFY_PATH: 1
54+
XDG_BIN_HOME: "{{.UV_DIR}}"
55+
silent: true
56+
cmds:
57+
- echo 'INSTALLING UV...'
58+
- echo '{{.UV_DIR}}'
59+
- echo '{{.UV_EXTERNAL}}'
60+
- mkdir -p "{{.UV_DIR}}"
61+
- wget -O install.sh https://astral.sh/uv/install.sh
62+
- chmod +x install.sh
63+
- ./install.sh
64+
- rm -f install.sh
65+
- "echo 'OK: UV INSTALLED'"
66+
lock:
67+
desc: "(advanced) Lock the uv environment"
68+
deps:
69+
- install
70+
cmds:
71+
- "{{.UV}} lock"
72+
sources:
73+
- "{{.ROOT_DIR}}/pyproject.toml"
74+
generates:
75+
- "{{.ROOT_DIR}}/uv.lock"
76+
77+
sync:
78+
desc: "(advanced) Sync the uv environment"
79+
silent: true
80+
status:
81+
- |
82+
if ! [ -f "{{.VENV}}/.uv_sync_opts" ]; then
83+
exit 1
84+
fi
85+
if [ "{{.UV_SYNC_OPTS}}" != "$(cat {{.VENV}}/.uv_sync_opts)" ]; then
86+
exit 1
87+
fi
88+
if ! [ -f "{{.VENV}}/.uv_lock.md5" ]; then
89+
exit 1
90+
fi
91+
if [ "$(md5sum uv.lock)" != "$(cat {{.VENV}}/.uv_lock.md5)" ]; then
92+
exit 1
93+
fi
94+
deps:
95+
- lock
96+
cmds:
97+
- "{{.UV}} sync {{.UV_SYNC_OPTS}}"
98+
- md5sum uv.lock >{{.VENV}}/.uv_lock.md5
99+
- echo "{{.UV_SYNC_OPTS}}" >{{.VENV}}/.uv_sync_opts
100+
101+
lint:
102+
deps:
103+
- sync
104+
internal: true
105+
silent: true
106+
cmds:
107+
- |
108+
if [ "{{.LINT_RUFF}}" = "1" ]; then
109+
if [ "{{.FIX}}" = "1" ]; then
110+
{{.RUFF}} format {{.RUFF_OPTS}} {{.RUFF_ARGS}}
111+
{{.RUFF}} check --fix {{.RUFF_OPTS}} {{.RUFF_ARGS}}
112+
else
113+
{{.RUFF}} format {{.RUFF_OPTS}} --check {{.RUFF_ARGS}}
114+
{{.RUFF}} check {{.RUFF_OPTS}} {{.RUFF_ARGS}}
115+
fi
116+
fi
117+
- |
118+
if [ "{{.LINT_MYPY}}" = "1" ]; then
119+
{{.MYPY}} {{.MYPY_OPTS}} {{.MYPY_ARGS}}
120+
fi
121+
122+
test:
123+
deps:
124+
- sync
125+
internal: true
126+
silent: true
127+
cmds:
128+
- |
129+
if [ "{{.TEST_PYTEST}}" = "1" ]; then
130+
if [ "{{.COVERAGE}}" = "1" ]; then
131+
{{.PYTEST}} {{.PYTEST_OPTS}} {{.PYTEST_COVERAGE_OPTS}} {{.PYTEST_ARGS}}
132+
else
133+
{{.PYTEST}} {{.PYTEST_OPTS}} {{.PYTEST_ARGS}}
134+
fi
135+
fi
136+
137+
build:
138+
internal: true
139+
silent: true
140+
deps:
141+
- sync
142+
cmds:
143+
- "{{.UV}} build"
144+
145+
publish:
146+
internal: true
147+
silent: true
148+
deps:
149+
- build
150+
cmds:
151+
- "{{.UV}} publish"
152+
153+
clean:
154+
internal: true
155+
silent: true
156+
cmds:
157+
- |
158+
if [ "{{.UV_EXTERNAL}}" = "0" ]; then
159+
rm -f "{{.UVX}}"
160+
rm -Rf {{.UV}}
161+
fi
162+
- rm -Rf .*_cache build
163+
- find . -type d -name __pycache__ -exec rm -Rf {} \; 2>/dev/null || true
164+
- "echo 'OK: CLEANED'"

Dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM python:3.12-alpine
2+
3+
ENV TASK=go-task
4+
ENV UV_NO_CACHE=1
5+
6+
RUN apk update && apk upgrade && apk add go-task && rm -rf /var/cache/apk/*
7+
RUN mkdir -p /app
8+
COPY .task /app/.task
9+
COPY Taskfile.yml README.md pyproject.toml uv.lock /app/
10+
RUN cd /app && export UV_SYNC_OPTS="--frozen --no-dev --no-install-project" && $TASK install
11+
COPY jinja_tree /app/jinja_tree/
12+
COPY entrypoint.sh /app/entrypoint.sh
13+
RUN cd /app && export UV_SYNC_OPTS="--frozen --no-dev --verbose" && $TASK install
14+
15+
WORKDIR /code
16+
17+
ENTRYPOINT ["/app/entrypoint.sh"]

0 commit comments

Comments
 (0)