Skip to content

Commit 51b741a

Browse files
authored
Switch from deadsnakes to pyenv for base pythons (#38)
Several other changes included: - update pre-commit hooks - add vscode repo settings for auto format - fix an issue with newer `lrzip` tools; it now spits out stderr noise unless the `-Q` option is set (previously just `-q` was enough) - switch from a bash script to invoke for driving the various tests _Intense_ hacks to support both running locally by mounting the cwd into the container; need to match host UID+GUID to permit sane read/writing to the mounted cwd... as well as running in CI, where we need to be root to clone the repo (why!!!), but we MUST be non-root to pass one of the tests (`can't write to directory`). Very sad workarounds to get everything going, I'm not too happy about it but it does work. Lastly, switch to running ci off a container hosted under dtrx-py organization on the github container registry. Invoke task for building + pushing the image. And updated documentation in the README.
1 parent e564bfa commit 51b741a

File tree

14 files changed

+314
-119
lines changed

14 files changed

+314
-119
lines changed

.dockerignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*
2+
!/requirements.txt
3+
!/entrypoint.sh

.github/workflows/main.yml

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,52 +10,76 @@ on:
1010

1111
jobs:
1212
build:
13-
runs-on: ubuntu-20.04
13+
runs-on: ubuntu-22.04
14+
container:
15+
image: ghcr.io/dtrx-py/dtrx:2022-09-16
16+
options: "--user=root"
1417

1518
steps:
16-
# checkout v2, with recursive submodule update
17-
- uses: actions/checkout@v2
19+
- uses: actions/checkout@v3
1820
with:
1921
submodules: recursive
2022

2123
- name: 🛠️ Build
2224
run: |
2325
pip install build==0.7.0
24-
python -m build
26+
python3 -m build
2527
2628
- uses: actions/upload-artifact@v2
2729
with:
2830
name: release-packages
2931
path: dist/
3032
test:
31-
runs-on: ubuntu-20.04
33+
runs-on: ubuntu-22.04
34+
container:
35+
image: ghcr.io/dtrx-py/dtrx:2022-09-16
36+
# we need to be root for checkout to work without pain
37+
options: "--entrypoint='' --user=root"
3238

3339
strategy:
3440
matrix:
3541
python: [py27, py36, py37, py38, py39, py3.10]
3642

3743
steps:
38-
# checkout v2, with recursive submodule update
39-
- uses: actions/checkout@v2
44+
- uses: actions/checkout@v3
4045
with:
4146
submodules: recursive
4247

43-
# build the Docker image we use to run the tests
4448
- name: 🧪 Run Tox Tests
45-
run: TOX_ARGS='-e ${{ matrix.python }}' ./test.sh
49+
run: |
50+
# switch to a non-root user; this is required for one of the dtrx
51+
# tests, which checks for an EACCESS error :/
52+
bash /entrypoint.sh bash -c \
53+
'sudo chown -R $(id -u):$(id -g) ${PWD} && TOX_ARGS="-e ${{ matrix.python }}" inv tox'
54+
55+
test-missing-file-command:
56+
runs-on: ubuntu-22.04
57+
58+
steps:
59+
- uses: actions/checkout@v3
60+
with:
61+
submodules: recursive
62+
63+
# build the Docker image we use to run the tests
64+
- name: ✅ Test When `file` Command Not Present
65+
run: |
66+
pip install -r requirements.txt
67+
inv test-nonexistent-file-cmd
4668
4769
manpage:
48-
runs-on: ubuntu-20.04
70+
runs-on: ubuntu-22.04
71+
container:
72+
image: ghcr.io/dtrx-py/dtrx:2022-09-16
73+
options: "--user=root"
4974

5075
steps:
51-
# checkout v2, with recursive submodule update
52-
- uses: actions/checkout@v2
76+
- uses: actions/checkout@v3
5377
with:
5478
submodules: recursive
5579

5680
# build the Docker image we use to run the tests
5781
- name: 📝 Generate Man Pages
58-
run: RUN_JOB=rst2man ./test.sh
82+
run: inv rst2man
5983

6084
# upload-artifact to save the output wheels
6185
- uses: actions/upload-artifact@v2
@@ -64,13 +88,14 @@ jobs:
6488
path: dtrx.1
6589

6690
windows:
67-
runs-on: ubuntu-20.04
91+
runs-on: ubuntu-22.04
6892

6993
steps:
70-
# checkout v2, with recursive submodule update
71-
- uses: actions/checkout@v2
94+
- uses: actions/checkout@v3
7295
with:
7396
submodules: recursive
7497

75-
- name: ❌ Verify Windows Install Fails
76-
run: RUN_JOB=windows ./test.sh
98+
- name: 🪟 Verify Windows Install Fails
99+
run: |
100+
pip install -r requirements.txt
101+
inv windows

.pre-commit-config.yaml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
exclude: web/
44
repos:
55
- repo: https://github.com/pre-commit/pre-commit-hooks
6-
rev: v4.1.0
6+
rev: v4.3.0
77
hooks:
88
- id: check-added-large-files # prevents giant files from being committed.
99
- id: check-case-conflict # checks for files that would conflict in case-insensitive filesystems.
@@ -21,11 +21,12 @@ repos:
2121
- id: fix-byte-order-marker # removes utf-8 byte order marker.
2222
- id: mixed-line-ending # replaces or checks mixed line ending.
2323
- id: pretty-format-json # This hook sets a standard for formatting JSON files.
24+
exclude: .vscode
2425
- id: requirements-txt-fixer # sorts entries in requirements.txt.
2526
- id: trailing-whitespace # trims trailing whitespace.
2627

2728
- repo: https://github.com/psf/black
28-
rev: 22.3.0
29+
rev: 22.8.0
2930
hooks:
3031
- id: black
3132

@@ -36,7 +37,7 @@ repos:
3637
files: (dtrx)|(\.(py)$)
3738

3839
- repo: https://github.com/sirosen/check-jsonschema
39-
rev: 0.14.1
40+
rev: 0.18.3
4041
hooks:
4142
- id: check-github-actions
4243
- id: check-github-workflows
@@ -52,11 +53,12 @@ repos:
5253
files: \./README\.md
5354

5455
- repo: https://github.com/pre-commit/mirrors-prettier
55-
rev: v2.6.1
56+
rev: v3.0.0-alpha.0
5657
hooks:
5758
- id: prettier
5859
args: [--write]
5960
files: \.(js|ts|jsx|tsx|css|less|html|json|markdown|md|yaml|yml)$
61+
exclude: .vscode
6062

6163
- repo: https://github.com/pryorda/dockerfilelint-precommit-hooks
6264
rev: v0.1.0
@@ -75,6 +77,6 @@ repos:
7577
- id: shellcheck
7678

7779
- repo: https://github.com/asottile/setup-cfg-fmt
78-
rev: v1.20.0
80+
rev: v2.0.0
7981
hooks:
8082
- id: setup-cfg-fmt

.python-version

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2.7.16
2+
3.6.15
3+
3.7.13
4+
3.8.13
5+
3.9.12
6+
3.10.4

.vscode/settings.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
{
2-
"markdown.extension.toc.levels": "2..6"
2+
"editor.formatOnSave": true,
3+
"python.formatting.provider": "black",
4+
"python.sortImports.args": [
5+
"--profile", "black"
6+
],
7+
"[python]": {
8+
"editor.codeActionsOnSave": {
9+
"source.organizeImports": true
10+
}
11+
}
312
}

Dockerfile

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,84 @@
1-
FROM ubuntu:focal-20200319
1+
2+
FROM ubuntu:jammy-20220815
23

34
ARG DEBIAN_FRONTEND=noninteractive
45

56
RUN apt-get update && apt-get install -y --no-install-recommends \
67
arj \
78
binutils \
89
brotli \
10+
build-essential \
11+
ca-certificates \
12+
clang \
913
cpio \
14+
curl \
1015
file \
16+
git \
1117
gzip \
1218
lhasa \
19+
libbz2-dev \
1320
libffi-dev \
21+
liblzma-dev \
22+
libncursesw5-dev \
23+
libreadline-dev \
24+
libsqlite3-dev \
25+
libssl-dev \
26+
libxml2-dev \
27+
libxmlsec1-dev \
28+
llvm \
1429
lrzip \
1530
lzip \
31+
make \
1632
p7zip-full \
17-
python-pip-whl \
18-
python2.7 \
33+
python3 \
34+
python3-dev \
1935
python3-pip \
20-
python3.8 \
36+
python3-venv \
37+
sudo \
38+
tk-dev \
2139
unrar \
2240
unzip \
2341
wget \
2442
xz-utils \
2543
zip \
44+
zlib1g-dev \
2645
zstd \
27-
software-properties-common && \
28-
add-apt-repository ppa:deadsnakes/ppa && apt-get update && \
29-
bash -c "\
30-
apt-get install -y \
31-
python2.7{,-dev} \
32-
python3.6{,-dev} \
33-
python3.7{,-dev,-distutils} \
34-
python3.8{,-dev} \
35-
python3.9{,-dev,-distutils}\
36-
python3.10{,-dev,-distutils}\
37-
python3-distutils" \
3846
&& rm -rf /var/lib/apt/lists/*
3947

40-
# create a user inside the container. if you specify your UID when building the
41-
# image, you can mount directories into the container with read-write access:
42-
# docker build -t "dtrx" -f Dockerfile --build-arg UID=$(id -u) .
43-
ARG UID=1010
44-
ARG UNAME=builder
45-
RUN useradd --uid ${UID} --create-home --user-group ${UNAME} && \
46-
echo "${UNAME}:${UNAME}" | chpasswd
48+
# pyenv
49+
RUN git clone --branch v2.3.4 https://github.com/pyenv/pyenv.git /pyenv
50+
ENV PYENV_ROOT /pyenv
51+
RUN /pyenv/bin/pyenv install 2.7.16
52+
# openssl version on jammy (3) is too new for python 3.6, and breaks :/
53+
# workaround is to use clang to build it
54+
# https://github.com/pyenv/pyenv/issues/2239#issuecomment-1079275184
55+
RUN CC=clang /pyenv/bin/pyenv install 3.6.15
56+
RUN /pyenv/bin/pyenv install 3.7.13
57+
RUN /pyenv/bin/pyenv install 3.8.13
58+
RUN /pyenv/bin/pyenv install 3.9.12
59+
RUN /pyenv/bin/pyenv install 3.10.4
60+
61+
ENV PATH=/pyenv/bin:${PATH}
4762

48-
ENV PATH=${PATH}:/home/${UNAME}/.local/bin
63+
# Python requirements
64+
COPY requirements.txt /tmp/requirements.txt
65+
RUN pip3 install -r /tmp/requirements.txt
4966

50-
USER ${UNAME}
67+
COPY entrypoint.sh /entrypoint.sh
68+
69+
ARG UID=1010
70+
ARG USERNAME=builder
71+
RUN echo "root:root" | chpasswd \
72+
&& adduser --disabled-password --uid "${UID}" --gecos "" "${USERNAME}" \
73+
&& echo "${USERNAME}:${USERNAME}" | chpasswd \
74+
&& echo "%${USERNAME} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/${USERNAME} \
75+
&& chmod 0440 /etc/sudoers.d/${USERNAME} \
76+
&& adduser ${USERNAME} sudo
5177

52-
# Need tox to run the tests, docutils for rst2man.py
53-
RUN pip3 install tox==3.15.2 docutils==0.16 pyyaml==5.4.1
78+
# Ensure sudo group users are not
79+
# asked for a password when using
80+
# sudo command by ammending sudoers file
81+
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> \
82+
/etc/sudoers
5483

55-
WORKDIR /workspace
84+
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]

README.md

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ pyversions](https://img.shields.io/pypi/pyversions/dtrx.svg?style=for-the-badge&
77

88
<!-- toc -->
99

10-
- [Changes in this repo](#changes-in-this-repo)
11-
- [Development](#development)
12-
- [Contributions](#contributions)
13-
- [Issues](#issues)
14-
- [Releases](#releases)
15-
- [Tests](#tests)
16-
- [Linting](#linting)
10+
- [dtrx](#dtrx)
11+
- [Changes in this repo](#changes-in-this-repo)
12+
- [Development](#development)
13+
- [Contributions](#contributions)
14+
- [Issues](#issues)
15+
- [Releases](#releases)
16+
- [Tests](#tests)
17+
- [Linting](#linting)
18+
- [Docker](#docker)
1719

1820
<!-- tocstop -->
1921

@@ -123,3 +125,31 @@ pre-commit install
123125

124126
pre-commit will run anytime `git commit` runs (disable with `--no-verify`). You
125127
can manually run it with `pre-commit run`.
128+
129+
### Docker
130+
131+
The tests in CI (and locally) can be run inside a Docker container, which
132+
provides all the tested python versions.
133+
134+
This image is defined at [`Dockerfile`](Dockerfile). It's pushed to the GitHub
135+
Container Registry so it can be managed by the `dtrx-py` organization on GitHub-
136+
Docker Hub charges for Organizations.
137+
138+
There are Invoke tasks for building + pushing the Docker image, which push both
139+
a `:latest` tag as well as a `:2022-09-16` ISO8601 numbered tag. The tag can
140+
then be updated in the GitHub actions runner.
141+
142+
> Note: there's a bit of complexity around how the image is used, because the
143+
> dtrx tests need to run as a non-root user (there's one test that checks for
144+
> error handling when the output directory is not accessible by the current
145+
> user). To deal with this, there's an entrypoint script that switches user to a
146+
> non-root user, but that still has read/write access to the mounted host volume
147+
> (which is the cwd, intended for local developement work). This is required on
148+
> Linux, where it's nice to have the host+container UID+GUID matching, so any
149+
> changes to the mounted host volume have the same permissions set.
150+
>
151+
> In the GitHub actions runner, we need to run inside the same container (to
152+
> have access to the correct python versions for testing), and the github action
153+
> for checkout assumes it can write to somewhat arbitrary locations in the file
154+
> system (basically root access). So we switch to the non-root user _after_
155+
> checkout.

0 commit comments

Comments
 (0)