gmtorch 0.0.0__tar.gz

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.
@@ -0,0 +1,12 @@
1
+ _commit: v1.6.0
2
+ _src_path: gh:superlinear-ai/substrate
3
+ author_email: tomass.timmermans@student.kit.edu
4
+ author_name: Tomass Marks Timmermans
5
+ project_description: Probabilistic Generative AI Using Gaussian Mixture
6
+ project_name: gmtorch
7
+ project_type: package
8
+ project_url: https://gitlab.kit.edu/ali.darijani/gmtorch
9
+ python_version: "3.12"
10
+ typing: strict
11
+ with_conventional_commits: true
12
+ with_typer_cli: false
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "gmtorch",
3
+ "dockerComposeFile": "../docker-compose.yml",
4
+ "service": "devcontainer",
5
+ "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}/",
6
+ "features": {
7
+ "ghcr.io/devcontainers-extra/features/starship:1": {}
8
+ },
9
+ "overrideCommand": true,
10
+ "remoteUser": "user",
11
+ "postStartCommand": "sudo chown -R user:user /opt/ && uv sync --python ${localEnv:PYTHON_VERSION:3.12} --resolution ${localEnv:RESOLUTION_STRATEGY:highest} --all-extras && pre-commit install --install-hooks",
12
+ "customizations": {
13
+ "jetbrains": {
14
+ "backend": "PyCharm",
15
+ "plugins": [
16
+ "com.github.copilot"
17
+ ]
18
+ },
19
+ "vscode": {
20
+ "extensions": [
21
+ "charliermarsh.ruff",
22
+ "GitHub.copilot",
23
+ "GitHub.copilot-chat",
24
+ "GitLab.gitlab-workflow",
25
+ "ms-azuretools.vscode-docker",
26
+ "ms-python.mypy-type-checker",
27
+ "ms-python.python",
28
+ "ms-toolsai.jupyter",
29
+ "ryanluker.vscode-coverage-gutters",
30
+ "tamasfe.even-better-toml",
31
+ "visualstudioexptteam.vscodeintellicode"
32
+ ],
33
+ "settings": {
34
+ "coverage-gutters.coverageFileNames": [
35
+ "reports/coverage.xml"
36
+ ],
37
+ "editor.codeActionsOnSave": {
38
+ "source.fixAll": "explicit",
39
+ "source.organizeImports": "explicit"
40
+ },
41
+ "editor.formatOnSave": true,
42
+ "[python]": {
43
+ "editor.defaultFormatter": "charliermarsh.ruff"
44
+ },
45
+ "[toml]": {
46
+ "editor.formatOnSave": false
47
+ },
48
+ "editor.rulers": [
49
+ 100
50
+ ],
51
+ "files.autoSave": "onFocusChange",
52
+ "github.copilot.chat.agent.enabled": true,
53
+ "github.copilot.chat.codesearch.enabled": true,
54
+ "github.copilot.chat.edits.enabled": true,
55
+ "github.copilot.nextEditSuggestions.enabled": true,
56
+ "jupyter.kernels.excludePythonEnvironments": [
57
+ "/usr/local/bin/python"
58
+ ],
59
+ "mypy-type-checker.importStrategy": "fromEnvironment",
60
+ "mypy-type-checker.preferDaemon": true,
61
+ "notebook.codeActionsOnSave": {
62
+ "notebook.source.fixAll": "explicit",
63
+ "notebook.source.organizeImports": "explicit"
64
+ },
65
+ "notebook.formatOnSave.enabled": true,
66
+ "python.defaultInterpreterPath": "/opt/venv/bin/python",
67
+ "python.terminal.activateEnvironment": false,
68
+ "python.testing.pytestEnabled": true,
69
+ "ruff.importStrategy": "fromEnvironment",
70
+ "ruff.logLevel": "warning",
71
+ "terminal.integrated.env.linux": {
72
+ "GIT_EDITOR": "code --wait"
73
+ },
74
+ "terminal.integrated.env.mac": {
75
+ "GIT_EDITOR": "code --wait"
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,8 @@
1
+ # Caches
2
+ .*_cache/
3
+
4
+ # Git
5
+ .git/
6
+
7
+ # Python
8
+ .venv/
@@ -0,0 +1,78 @@
1
+ # Coverage.py
2
+ htmlcov/
3
+ reports/
4
+
5
+ # Copier
6
+ *.rej
7
+
8
+ # Data
9
+ *.csv*
10
+ *.dat*
11
+ *.pickle*
12
+ *.xls*
13
+ *.zip*
14
+ data/
15
+
16
+ # direnv
17
+ .envrc
18
+
19
+ # dotenv
20
+ .env
21
+
22
+ # Hypothesis
23
+ .hypothesis/
24
+
25
+ # Jupyter
26
+ *.ipynb
27
+ .ipynb_checkpoints/
28
+ notebooks/
29
+
30
+ # macOS
31
+ .DS_Store
32
+
33
+ # mise
34
+ mise.local.toml
35
+
36
+ # MkDocs
37
+ site/
38
+
39
+ # Sphinx
40
+ docs/_build/
41
+ docs/source/reference/
42
+ docs/source/modules.rst
43
+ docs/source/tests*.rst
44
+
45
+ # mypy
46
+ .dmypy.json
47
+ .mypy_cache/
48
+
49
+ # Node.js
50
+ node_modules/
51
+
52
+ # PyCharm
53
+ .idea/
54
+
55
+ # pyenv
56
+ .python-version
57
+
58
+ # pytest
59
+ .pytest_cache/
60
+
61
+ # Python
62
+ __pycache__/
63
+ *.egg-info/
64
+ *.py[cdo]
65
+ .venv/
66
+ dist/
67
+
68
+ # Ruff
69
+ .ruff_cache/
70
+
71
+ # Terraform
72
+ .terraform/
73
+
74
+ # uv
75
+ uv.lock
76
+
77
+ # VS Code
78
+ .vscode/
@@ -0,0 +1,307 @@
1
+ # You can override the included template(s) by including variable overrides
2
+ # SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
3
+ # Secret Detection customization: https://docs.gitlab.com/user/application_security/secret_detection/pipeline/configure
4
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
5
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
6
+ # Note that environment variables can be set in several places
7
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
8
+ stages:
9
+ - code-validation
10
+ - test
11
+ - build
12
+ - docs
13
+ - publish
14
+
15
+ include:
16
+ - template: Security/SAST.gitlab-ci.yml
17
+ - template: Security/Secret-Detection.gitlab-ci.yml
18
+
19
+ variables:
20
+ SECRET_DETECTION_ENABLED: "true"
21
+ GIT_STRATEGY: clone
22
+ GIT_CLEAN_FLAGS: -ffdx
23
+
24
+ # Set the tag to the runner you want to use (also works for individual jobs)
25
+ # KIT runners: https://docs.gitlab.kit.edu/en/gitlab_runner/
26
+
27
+ # CODE VALIDATION
28
+ secret_detection:
29
+ stage: code-validation
30
+
31
+ linting:
32
+ stage: code-validation
33
+ image: python:3.12-alpine
34
+ before_script:
35
+ - pip install ruff mypy
36
+ - pip install --no-deps -e .
37
+ script:
38
+ - mkdir -p reports
39
+ - ruff check --force-exclude --extend-fixable=ERA001,F401,F841,T201,T203 --output-format=gitlab . > reports/ruff-codequality.json || true
40
+ - ruff check --force-exclude --extend-fixable=ERA001,F401,F841,T201,T203 .
41
+ - ruff format --check --force-exclude .
42
+ - mypy src
43
+ artifacts:
44
+ when: always
45
+ reports:
46
+ junit: reports/mypy.xml
47
+ codequality: reports/ruff-codequality.json
48
+ paths:
49
+ - reports/mypy.xml
50
+ - reports/ruff-codequality.json
51
+ allow_failure: false
52
+
53
+ # TEST
54
+ sast:
55
+ stage: test
56
+
57
+ # Tests run unit tests in the GPU-enabled Docker image
58
+ tests:
59
+ stage: test
60
+ image: nvidia/cuda:12.8.0-runtime-ubuntu24.04
61
+ variables:
62
+ UV_PYTHON_VERSIONS: "3.10 3.11 3.12 3.13 3.14"
63
+ before_script:
64
+ - apt-get update
65
+ - apt-get install -y --no-install-recommends curl ca-certificates
66
+ - curl -LsSf https://astral.sh/uv/install.sh | sh
67
+ - export PATH="/root/.local/bin:$PATH"
68
+ - uv python install $UV_PYTHON_VERSIONS
69
+ script:
70
+ - for version in $UV_PYTHON_VERSIONS; do
71
+ echo "Running tests with Python $version";
72
+ uv venv --python $version .venv-$version;
73
+ uv pip install --python .venv-$version/bin/python --index-url https://download.pytorch.org/whl/cu128 torch torchvision;
74
+ uv pip install --python .venv-$version/bin/python pytest pytest-xdist;
75
+ uv pip install --python .venv-$version/bin/python -e .;
76
+ .venv-$version/bin/pytest -n auto -v --junitxml=junit-$version.xml tests/ || exit 1;
77
+ done
78
+ artifacts:
79
+ when: on_failure
80
+ expire_in: 1 week
81
+ reports:
82
+ junit: junit-*.xml
83
+ paths:
84
+ - junit-*.xml
85
+ # Change to gpu enabled runner and remove allow_failure once available
86
+ tags:
87
+ - local
88
+ allow_failure: true
89
+
90
+ # BUILD
91
+ build_project:
92
+ stage: build
93
+ image: python:3.12-alpine
94
+ tags:
95
+ - kgr2-instance-standard
96
+ before_script:
97
+ - apk add --no-cache git curl jq
98
+ - pip install build
99
+ script:
100
+ - |
101
+ BASE_VERSION=$(grep -m 1 '^version = ' pyproject.toml | tr -s ' ' | tr -d '"' | tr -d "'" | cut -d' ' -f3)
102
+ PACKAGE_NAME=$(grep -m 1 '^name = ' pyproject.toml | tr -s ' ' | tr -d '"' | tr -d "'" | cut -d' ' -f3)
103
+ BUILD_VERSION="$BASE_VERSION"
104
+
105
+ echo "Fetching existing versions from PyPI..."
106
+ PYPI_RESPONSE=$(curl -s "https://pypi.org/pypi/$PACKAGE_NAME/json" 2>/dev/null || echo '{"releases":{}}')
107
+
108
+ if echo "$PYPI_RESPONSE" | jq -e '.releases' > /dev/null 2>&1; then
109
+ PACKAGE_EXISTS=true
110
+ echo "✅ Package found on PyPI"
111
+ else
112
+ PACKAGE_EXISTS=false
113
+ echo "ℹ️ Package not yet published on PyPI"
114
+ fi
115
+ echo ""
116
+
117
+
118
+ if [ "$CI_COMMIT_BRANCH" = "main" ] || [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" = "main" ]; then
119
+ echo "Building stable version: $BUILD_VERSION"
120
+
121
+ if [ "$PACKAGE_EXISTS" = "true" ] && echo "$PYPI_RESPONSE" | jq -e ".releases.\"$BUILD_VERSION\"" > /dev/null 2>&1; then
122
+ echo "❌ ERROR: Version $BUILD_VERSION already exists on PyPI!"
123
+ echo ""
124
+ echo "Please bump the version before merging to main:"
125
+ echo "--> cz bump"
126
+ exit 1
127
+ fi
128
+
129
+ elif [ "$CI_COMMIT_BRANCH" = "develop" ]; then
130
+ echo "Checking existing dev versions on PyPI..."
131
+
132
+ if [ "$PACKAGE_EXISTS" = "true" ]; then
133
+ EXISTING_VERSIONS=$(echo "$PYPI_RESPONSE" | jq -r '.releases | keys[]' | grep "^${BASE_VERSION}\.dev" || echo "")
134
+ else
135
+ EXISTING_VERSIONS=""
136
+ fi
137
+
138
+ if [ -z "$EXISTING_VERSIONS" ]; then
139
+ DEV_NUMBER=0
140
+ echo "No existing dev versions found, starting with dev0"
141
+ else
142
+ echo "Existing dev versions:"
143
+ echo "$EXISTING_VERSIONS"
144
+
145
+ HIGHEST_DEV=$(echo "$EXISTING_VERSIONS" | sed "s/${BASE_VERSION}\.dev//" | sort -n | tail -1)
146
+ DEV_NUMBER=$((HIGHEST_DEV + 1))
147
+ echo "Highest existing: dev${HIGHEST_DEV}"
148
+ echo "Using: dev${DEV_NUMBER}"
149
+ fi
150
+
151
+ BUILD_VERSION="${BASE_VERSION}.dev${DEV_NUMBER}"
152
+ echo "Building development version: $BUILD_VERSION"
153
+
154
+ else
155
+ SHORT_SHA=$(git rev-parse --short=8 HEAD)
156
+ BUILD_VERSION="${BASE_VERSION}.dev0+${SHORT_SHA}"
157
+ echo "Building feature branch version: $BUILD_VERSION"
158
+ echo "⚠️ Note: This version should NOT be published"
159
+ fi
160
+
161
+ sed -i "0,/^version = .*/s//version = \"$BUILD_VERSION\"/" pyproject.toml
162
+
163
+ echo "Updated pyproject.toml version:"
164
+ grep -m 1 '^version = ' pyproject.toml
165
+ echo ""
166
+
167
+ echo "Building package..."
168
+ python -m build --sdist --wheel --outdir dist
169
+
170
+ echo "BUILD_VERSION=${BUILD_VERSION}" >> build.env
171
+ echo "PACKAGE_NAME=${PACKAGE_NAME}" >> build.env
172
+
173
+ echo ""
174
+ echo "✅ Successfully built version: $BUILD_VERSION"
175
+ echo ""
176
+
177
+ artifacts:
178
+ when: on_success
179
+ expire_in: 1 week
180
+ reports:
181
+ dotenv: build.env
182
+ paths:
183
+ - dist/*.whl
184
+ - dist/*.tar.gz
185
+ rules:
186
+ - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
187
+
188
+ # DOCS
189
+ generate_docs:
190
+ stage: docs
191
+ image: python:3.12-alpine
192
+ before_script:
193
+ - pip install sphinx
194
+ script:
195
+ - |
196
+ echo "Generating Sphinx documentation..."
197
+ sphinx-apidoc -f -o docs/source/reference src/gmtorch
198
+ sphinx-build -b html docs/source docs/_build/html
199
+
200
+ echo "✅ Documentation generated"
201
+ artifacts:
202
+ paths:
203
+ - docs/_build
204
+ rules:
205
+ - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
206
+
207
+ # PUBLISH
208
+ publish_pages:
209
+ stage: publish
210
+ image: alpine:latest
211
+ needs: ["generate_docs"]
212
+ script:
213
+ - |
214
+ echo "Publishing to GitLab Pages..."
215
+ rm -rf public
216
+ cp -r docs/_build/html public
217
+ echo "✅ Documentation published to GitLab Pages"
218
+ artifacts:
219
+ paths:
220
+ - public
221
+ rules:
222
+ - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
223
+
224
+ # Publishes project to GitLab Package Registry and PyPI
225
+ publish_project:
226
+ stage: publish
227
+ image: python:3.12-alpine
228
+ when: manual
229
+ before_script:
230
+ - pip install twine
231
+ script:
232
+ - |
233
+ echo "Publishing version $BUILD_VERSION"
234
+ echo "Package: $PACKAGE_NAME"
235
+
236
+ echo "📦 Publishing to GitLab Package Registry..."
237
+ TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi dist/*.whl dist/*.tar.gz
238
+ echo "✅ GitLab Package Registry upload complete"
239
+
240
+ echo "📦 Publishing to PyPI..."
241
+ python -m twine upload dist/*.whl dist/*.tar.gz
242
+ echo "✅ PyPI upload complete"
243
+ variables:
244
+ TWINE_USERNAME: __token__
245
+ TWINE_PASSWORD: ${PYPI_API_TOKEN}
246
+ rules:
247
+ - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
248
+
249
+ publish_docker:
250
+ stage: publish
251
+ tags:
252
+ - kgr2-instance-standard
253
+ image:
254
+ name: ghcr.io/kaniko-build/dist/chainguard-dev-kaniko/executor:latest-debug
255
+ entrypoint: [""]
256
+ when: manual
257
+ variables:
258
+ DOCKER_CONFIG: "/kaniko/.docker"
259
+ DOCKERFILE_PATH: "$CI_PROJECT_DIR/Dockerfile"
260
+ CONTEXT: "$CI_PROJECT_DIR"
261
+ CACHE_REPO: "$DOCKERHUB_REPO"
262
+ before_script:
263
+ - mkdir -p /kaniko/.docker
264
+ - |
265
+ if [ -z "${DOCKERHUB_USERNAME}" ] || [ -z "${DOCKERHUB_PASSWORD}" ]; then
266
+ echo "DOCKERHUB_USERNAME or DOCKERHUB_PASSWORD is not set. Please define them in CI/CD variables." >&2
267
+ exit 1
268
+ fi
269
+ cat > /kaniko/.docker/config.json <<EOF
270
+ {
271
+ "auths": {
272
+ "https://index.docker.io/v1/": {
273
+ "auth": "$(echo -n ${DOCKERHUB_USERNAME}:${DOCKERHUB_PASSWORD} | base64)"
274
+ }
275
+ }
276
+ }
277
+ EOF
278
+ script:
279
+ - |
280
+ # Determine tags based on branch
281
+ if [ "$CI_COMMIT_BRANCH" = "main" ]; then
282
+ echo "Publishing stable Docker image: latest"
283
+ /kaniko/executor \
284
+ --context "$CONTEXT" \
285
+ --dockerfile "$DOCKERFILE_PATH" \
286
+ --destination "$DOCKERHUB_REPO:latest" \
287
+ --cache=true \
288
+ --cache-repo "$CACHE_REPO" \
289
+ --compressed-caching=false \
290
+ --skip-unused-stages \
291
+ --single-snapshot \
292
+ --target base
293
+ elif [ "$CI_COMMIT_BRANCH" = "develop" ]; then
294
+ echo "Publishing development Docker image: develop"
295
+ /kaniko/executor \
296
+ --context "$CONTEXT" \
297
+ --dockerfile "$DOCKERFILE_PATH" \
298
+ --destination "$DOCKERHUB_REPO:develop" \
299
+ --cache=true \
300
+ --cache-repo "$CACHE_REPO" \
301
+ --compressed-caching=false \
302
+ --skip-unused-stages \
303
+ --single-snapshot \
304
+ --target base
305
+ fi
306
+ rules:
307
+ - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
@@ -0,0 +1,73 @@
1
+ # https://pre-commit.com
2
+ default_install_hook_types: [commit-msg, pre-commit]
3
+ default_stages: [pre-commit, manual]
4
+ fail_fast: true
5
+ repos:
6
+ - repo: meta
7
+ hooks:
8
+ - id: check-useless-excludes
9
+ - repo: https://github.com/pre-commit/pygrep-hooks
10
+ rev: v1.10.0
11
+ hooks:
12
+ - id: python-check-mock-methods
13
+ - id: python-use-type-annotations
14
+ - id: rst-backticks
15
+ - id: rst-directive-colons
16
+ - id: rst-inline-touching-normal
17
+ - id: text-unicode-replacement-char
18
+ - repo: https://github.com/pre-commit/pre-commit-hooks
19
+ rev: v5.0.0
20
+ hooks:
21
+ - id: check-added-large-files
22
+ - id: check-ast
23
+ - id: check-builtin-literals
24
+ - id: check-case-conflict
25
+ - id: check-docstring-first
26
+ - id: check-illegal-windows-names
27
+ - id: check-json
28
+ - id: check-merge-conflict
29
+ - id: check-shebang-scripts-are-executable
30
+ - id: check-symlinks
31
+ - id: check-toml
32
+ - id: check-vcs-permalinks
33
+ - id: check-xml
34
+ - id: check-yaml
35
+ - id: debug-statements
36
+ - id: destroyed-symlinks
37
+ - id: detect-private-key
38
+ - id: end-of-file-fixer
39
+ types: [python]
40
+ - id: fix-byte-order-marker
41
+ - id: mixed-line-ending
42
+ - id: name-tests-test
43
+ args: [--pytest-test-first]
44
+ - id: trailing-whitespace
45
+ types: [python]
46
+ - repo: local
47
+ hooks:
48
+ - id: commitizen
49
+ name: commitizen
50
+ entry: cz check
51
+ args: [--commit-msg-file]
52
+ require_serial: true
53
+ language: system
54
+ stages: [commit-msg]
55
+ - id: ruff-check
56
+ name: ruff check
57
+ entry: ruff check
58
+ args: ["--force-exclude", "--extend-fixable=ERA001,F401,F841,T201,T203"]
59
+ require_serial: true
60
+ language: system
61
+ types_or: [python, pyi]
62
+ - id: ruff-format
63
+ name: ruff format
64
+ entry: ruff format
65
+ args: [--force-exclude]
66
+ require_serial: true
67
+ language: system
68
+ types_or: [python, pyi]
69
+ - id: mypy
70
+ name: mypy
71
+ entry: mypy
72
+ language: system
73
+ types: [python]
@@ -0,0 +1,67 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ # Build stage: Create the image with dependencies
4
+ FROM nvidia/cuda:12.6.0-runtime-ubuntu24.04 AS base
5
+
6
+ ENV DEBIAN_FRONTEND=noninteractive
7
+
8
+ RUN apt-get update && apt-get install -y --no-install-recommends \
9
+ python3.12 \
10
+ python3.12-venv \
11
+ && rm -rf /var/lib/apt/lists/* \
12
+ && apt-get clean
13
+
14
+ # Install uv
15
+ COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
16
+
17
+ # Set working directory
18
+ WORKDIR /app
19
+
20
+ # Setup virtual environment
21
+ ENV VIRTUAL_ENV=/opt/venv
22
+ ENV PATH=$VIRTUAL_ENV/bin:$PATH
23
+ ENV UV_PROJECT_ENVIRONMENT=$VIRTUAL_ENV
24
+
25
+ COPY pyproject.toml README.md ./
26
+ COPY src ./src
27
+ COPY tests ./tests
28
+
29
+ # Create venv and install dependencies
30
+ RUN uv venv "$VIRTUAL_ENV" && \
31
+ uv pip install --no-cache -e .
32
+
33
+ FROM base AS dev
34
+
35
+ # Install git, sudo, ssh, make for development; ensure user with UID 1000 exists, set permissions and configure git
36
+ # apt-get required as we clean it up in the base image to publish smaller images
37
+ RUN apt-get update && apt-get install -y --no-install-recommends \
38
+ git \
39
+ sudo \
40
+ openssh-client \
41
+ make \
42
+ && rm -rf /var/lib/apt/lists/* \
43
+ && apt-get clean && \
44
+ if id -u 1000 > /dev/null 2>&1; then \
45
+ EXISTING_USER=$(id -un 1000) && \
46
+ if [ "$EXISTING_USER" != "user" ]; then \
47
+ usermod -l user -d /home/user -m "$EXISTING_USER" && \
48
+ groupmod -n user $(id -gn 1000) 2>/dev/null || true; \
49
+ fi; \
50
+ else \
51
+ groupadd --gid 1000 user && \
52
+ useradd --create-home --no-log-init --gid 1000 --uid 1000 --shell /usr/bin/bash user; \
53
+ fi && \
54
+ chown -R 1000:1000 /opt/venv && \
55
+ echo '%sudo ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/nopasswd && \
56
+ chmod 0440 /etc/sudoers.d/nopasswd && \
57
+ usermod -aG sudo user && \
58
+ git config --system --add safe.directory '*'
59
+
60
+ USER user
61
+
62
+ # Configure the shell for UID 1000
63
+ RUN mkdir -p ~/.history/ && \
64
+ echo 'HISTFILE=~/.history/.bash_history' >> ~/.bashrc && \
65
+ echo 'bind "\e[A": history-search-backward' >> ~/.bashrc && \
66
+ echo 'bind "\e[B": history-search-forward' >> ~/.bashrc && \
67
+ echo 'eval "$(starship init bash)"' >> ~/.bashrc