Skip to content

Commit 008ea02

Browse files
committed
Merge branch 'dev'
2 parents 195ea39 + d728a37 commit 008ea02

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1045
-656
lines changed

.devcontainer/Dockerfile

+26-20
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,37 @@
1-
# ideas from https://www.docker.com/blog/containerized-python-development-part-1/
1+
# This file is for use as a devcontainer and a runtime container
2+
#
3+
# The devcontainer should use the build target and run as root with podman
4+
# or docker with user namespaces.
5+
#
6+
FROM python:3.10 as build
27

3-
# This file is for use as a .vscode devcontainer as well as a runtime
4-
# container. The devcontainer should be rootful and use podman or docker
5-
# with user namespaces.
8+
ARG PIP_OPTIONS
69

7-
ARG BASE="mcr.microsoft.com/vscode/devcontainers/python:0-3.10-bullseye"
8-
FROM ${BASE} as base
10+
# Add any system dependencies for the developer/build environment here e.g.
11+
# RUN apt-get update && apt-get upgrade -y && \
12+
# apt-get install -y --no-install-recommends \
13+
# desired-packages \
14+
# && rm -rf /var/lib/apt/lists/*
915

10-
# use root to pin where the packages will install
11-
USER root
12-
ENV PATH=/root/.local/bin:$PATH
16+
# set up a virtual environment and put it in PATH
17+
RUN python -m venv /venv
18+
ENV PATH=/venv/bin:$PATH
1319

14-
FROM base as developer
20+
# Copy any required context for the pip install over
21+
COPY . /context
22+
WORKDIR /context
1523

16-
WORKDIR /workspace
17-
COPY . .
24+
# install python package into /venv
25+
RUN pip install ${PIP_OPTIONS}
1826

19-
# install runtime from DIST if there is one
20-
RUN mkdir -p /root/.local && \
21-
if [ -d dist ] ; then \
22-
touch requirements.txt && \
23-
pip install --user -r requirements.txt dist/*.whl ; \
24-
fi
27+
FROM python:3.10-slim as runtime
2528

26-
FROM base as runtime
29+
# Add apt-get system dependecies for runtime here if needed
2730

28-
COPY --from=developer /root/.local /root/.local
31+
# copy the virtual environment from the build stage and put it in PATH
32+
COPY --from=build /venv/ /venv/
33+
ENV PATH=/venv/bin:$PATH
2934

35+
# change this entrypoint if it is not the same as the repo
3036
ENTRYPOINT ["ibek"]
3137
CMD ["--version"]

.devcontainer/devcontainer.json

+16-43
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,41 @@
1-
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
2-
// https://github.com/microsoft/vscode-dev-containers/tree/v0.231.6/containers/python-3
1+
// For format details, see https://aka.ms/devcontainer.json
32
{
4-
"name": "Python 3",
3+
"name": "Python 3 Developer Container",
54
"build": {
65
"dockerfile": "Dockerfile",
7-
"target": "developer",
8-
"context": "..",
9-
"args": {}
6+
"target": "build",
7+
// Only upgrade pip, we will install the project below
8+
"args": {
9+
"PIP_OPTIONS": "--upgrade pip"
10+
}
1011
},
1112
"remoteEnv": {
1213
"DISPLAY": "${localEnv:DISPLAY}"
1314
},
1415
// Set *default* container specific settings.json values on container create.
1516
"settings": {
16-
"python.defaultInterpreterPath": "/usr/local/bin/python",
17-
"python.linting.enabled": true,
18-
"python.linting.pylintEnabled": true,
19-
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
20-
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
21-
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
22-
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
23-
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
24-
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
25-
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
26-
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
27-
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
17+
"python.defaultInterpreterPath": "/venv/bin/python"
2818
},
2919
// Add the IDs of extensions you want installed when the container is created.
3020
"extensions": [
3121
"ms-python.python",
32-
"ms-python.vscode-pylance",
33-
"streetsidesoftware.code-spell-checker",
34-
"ryanluker.vscode-coverage-gutters",
35-
"mhutchie.git-graph",
36-
"eamodio.gitlens",
37-
"gruntfuggly.todo-tree",
38-
"redhat.vscode-yaml",
39-
"nsd.vscode-epics",
40-
"alefragnani.bookmarks"
22+
"ms-python.vscode-pylance"
4123
],
42-
"features": {
43-
//"docker-from-docker": "20.10",
44-
"git": "os-provided"
45-
},
46-
// Use 'forwardPorts' to make a list of ports inside the container available locally.
47-
// "forwardPorts": [],
48-
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
49-
// "remoteUser": "vscode",
5024
// Make sure the files we are mapping into the container exist on the host
51-
"initializeCommand": "bash -c 'for i in $HOME/.inputrc $HOME/.bashrc_dev; do [ -f $i ] || touch $i; done'",
25+
"initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'",
5226
"runArgs": [
53-
"--privileged",
5427
"--net=host",
28+
"--security-opt=label=type:container_runtime_t",
5529
"-v=${localEnv:HOME}/.ssh:/root/.ssh",
56-
"-v=${localEnv:HOME}/.bashrc_dev:/root/.bashrc",
5730
"-v=${localEnv:HOME}/.inputrc:/root/.inputrc"
5831
],
5932
"mounts": [
60-
// map in home directory - not strictly necessary but may be useful
33+
// map in home directory - not strictly necessary but useful
6134
"source=${localEnv:HOME},target=${localEnv:HOME},type=bind,consistency=cached"
6235
],
63-
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
64-
"workspaceFolder": "/workspace",
36+
// make the workspace folder the same inside and outside of the container
37+
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
38+
"workspaceFolder": "${localWorkspaceFolder}",
6539
// After the container is created, install the python project in editable form
66-
// This installs into the system python of the container
67-
"postCreateCommand": "pip install $([ -f requirements_dev.txt ] && echo -r requirements_dev.txt ) -e .[dev]"
40+
"postCreateCommand": "pip install -e .[dev]"
6841
}

.gitattributes

-1
This file was deleted.

.github/CONTRIBUTING.rst

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Contributing to the project
2+
===========================
3+
4+
Contributions and issues are most welcome! All issues and pull requests are
5+
handled through GitHub_. Also, please check for any existing issues before
6+
filing a new one. If you have a great idea but it involves big changes, please
7+
file a ticket before making a pull request! We want to make sure you don't spend
8+
your time coding something that might not fit the scope of the project.
9+
10+
.. _GitHub: https://github.com/DiamondLightSource/python3-pip-skeleton/issues
11+
12+
Issue or Discussion?
13+
--------------------
14+
15+
Github also offers discussions_ as a place to ask questions and share ideas. If
16+
your issue is open ended and it is not obvious when it can be "closed", please
17+
raise it as a discussion instead.
18+
19+
.. _discussions: https://github.com/DiamondLightSource/python3-pip-skeleton/discussions
20+
21+
Code coverage
22+
-------------
23+
24+
While 100% code coverage does not make a library bug-free, it significantly
25+
reduces the number of easily caught bugs! Please make sure coverage remains the
26+
same or is improved by a pull request!
27+
28+
Developer guide
29+
---------------
30+
31+
The `Developer Guide`_ contains information on setting up a development
32+
environment, running the tests and what standards the code and documentation
33+
should follow.
34+
35+
.. _Developer Guide: https://diamondlightsource.github.io/python3-pip-skeleton/main/developer/how-to/contribute.html
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Install requirements
2+
description: Run pip install with requirements and upload resulting requirements
3+
inputs:
4+
requirements_file:
5+
description: Name of requirements file to use and upload
6+
required: true
7+
install_options:
8+
description: Parameters to pass to pip install
9+
required: true
10+
python_version:
11+
description: Python version to install
12+
default: "3.10"
13+
14+
runs:
15+
using: composite
16+
17+
steps:
18+
- name: Setup python
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: ${{ inputs.python_version }}
22+
23+
- name: Pip install
24+
run: |
25+
touch ${{ inputs.requirements_file }}
26+
# -c uses requirements.txt as constraints, see 'Validate requirements file'
27+
pip install -c ${{ inputs.requirements_file }} ${{ inputs.install_options }}
28+
shell: bash
29+
30+
- name: Create lockfile
31+
run: |
32+
mkdir -p lockfiles
33+
pip freeze --exclude-editable > lockfiles/${{ inputs.requirements_file }}
34+
# delete the self referencing line and make sure it isn't blank
35+
sed -i '/file:/d' lockfiles/${{ inputs.requirements_file }}
36+
shell: bash
37+
38+
- name: Upload lockfiles
39+
uses: actions/upload-artifact@v3
40+
with:
41+
name: lockfiles
42+
path: lockfiles
43+
44+
# This eliminates the class of problems where the requirements being given no
45+
# longer match what the packages themselves dictate. E.g. In the rare instance
46+
# where I install some-package which used to depend on vulnerable-dependency
47+
# but now uses good-dependency (despite being nominally the same version)
48+
# pip will install both if given a requirements file with -r
49+
- name: If requirements file exists, check it matches pip installed packages
50+
run: |
51+
if [ -s ${{ inputs.requirements_file }} ]; then
52+
if ! diff -u ${{ inputs.requirements_file }} lockfiles/${{ inputs.requirements_file }}; then
53+
echo "Error: ${{ inputs.requirements_file }} need the above changes to be exhaustive"
54+
exit 1
55+
fi
56+
fi
57+
shell: bash

.github/dependabot.yml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5+
6+
version: 2
7+
updates:
8+
- package-ecosystem: "github-actions"
9+
directory: "/"
10+
schedule:
11+
interval: "weekly"
12+
13+
- package-ecosystem: "pip"
14+
directory: "/"
15+
schedule:
16+
interval: "weekly"

.github/pages/make_switcher.py

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import json
2+
import logging
3+
from argparse import ArgumentParser
4+
from pathlib import Path
5+
from subprocess import CalledProcessError, check_output
6+
from typing import List, Optional
7+
8+
9+
def report_output(stdout: bytes, label: str) -> List[str]:
10+
ret = stdout.decode().strip().split("\n")
11+
print(f"{label}: {ret}")
12+
return ret
13+
14+
15+
def get_branch_contents(ref: str) -> List[str]:
16+
"""Get the list of directories in a branch."""
17+
stdout = check_output(["git", "ls-tree", "-d", "--name-only", ref])
18+
return report_output(stdout, "Branch contents")
19+
20+
21+
def get_sorted_tags_list() -> List[str]:
22+
"""Get a list of sorted tags in descending order from the repository."""
23+
stdout = check_output(["git", "tag", "-l", "--sort=-v:refname"])
24+
return report_output(stdout, "Tags list")
25+
26+
27+
def get_versions(ref: str, add: Optional[str], remove: Optional[str]) -> List[str]:
28+
"""Generate the file containing the list of all GitHub Pages builds."""
29+
# Get the directories (i.e. builds) from the GitHub Pages branch
30+
try:
31+
builds = set(get_branch_contents(ref))
32+
except CalledProcessError:
33+
builds = set()
34+
logging.warning(f"Cannot get {ref} contents")
35+
36+
# Add and remove from the list of builds
37+
if add:
38+
builds.add(add)
39+
if remove:
40+
assert remove in builds, f"Build '{remove}' not in {sorted(builds)}"
41+
builds.remove(remove)
42+
43+
# Get a sorted list of tags
44+
tags = get_sorted_tags_list()
45+
46+
# Make the sorted versions list from main branches and tags
47+
versions: List[str] = []
48+
for version in ["master", "main"] + tags:
49+
if version in builds:
50+
versions.append(version)
51+
builds.remove(version)
52+
53+
# Add in anything that is left to the bottom
54+
versions += sorted(builds)
55+
print(f"Sorted versions: {versions}")
56+
return versions
57+
58+
59+
def write_json(path: Path, repository: str, versions: str):
60+
org, repo_name = repository.split("/")
61+
struct = [
62+
dict(version=version, url=f"https://{org}.github.io/{repo_name}/{version}/")
63+
for version in versions
64+
]
65+
text = json.dumps(struct, indent=2)
66+
print(f"JSON switcher:\n{text}")
67+
path.write_text(text)
68+
69+
70+
def main(args=None):
71+
parser = ArgumentParser(
72+
description="Make a versions.txt file from gh-pages directories"
73+
)
74+
parser.add_argument(
75+
"--add",
76+
help="Add this directory to the list of existing directories",
77+
)
78+
parser.add_argument(
79+
"--remove",
80+
help="Remove this directory from the list of existing directories",
81+
)
82+
parser.add_argument(
83+
"repository",
84+
help="The GitHub org and repository name: ORG/REPO",
85+
)
86+
parser.add_argument(
87+
"output",
88+
type=Path,
89+
help="Path of write switcher.json to",
90+
)
91+
args = parser.parse_args(args)
92+
93+
# Write the versions file
94+
versions = get_versions("origin/gh-pages", args.add, args.remove)
95+
write_json(args.output, args.repository, versions)
96+
97+
98+
if __name__ == "__main__":
99+
main()

0 commit comments

Comments
 (0)