Skip to content

Commit 4ec3b7a

Browse files
authored
Merge pull request #88 from epics-containers/edge-containers
Adopt python copier template
2 parents e7d0972 + 188a01d commit 4ec3b7a

File tree

125 files changed

+679
-867
lines changed

Some content is hidden

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

125 files changed

+679
-867
lines changed

.copier-answers.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Changes here will be overwritten by Copier
2+
_commit: 1.3.0
3+
_src_path: gh:DiamondLightSource/python-copier-template
4+
author_email: [email protected]
5+
author_name: Giles Knap
6+
component_owner: group:default/sscc
7+
description: Documentation for the epics-containers framework
8+
distribution_name: epic-containers
9+
docker: false
10+
docs_type: sphinx
11+
git_platform: github.com
12+
github_org: epics-containers
13+
package_name: epics-containers
14+
repo_name: epic-containers.github.io
15+
type_checker: mypy

.devcontainer/devcontainer.json

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,44 @@
33
"name": "Python 3 Developer Container",
44
"build": {
55
"dockerfile": "../Dockerfile",
6-
"target": "build",
7-
// Only upgrade pip, we will install the project below
8-
"args": {
9-
"PIP_OPTIONS": "--upgrade pip"
10-
}
6+
"target": "developer"
117
},
128
"remoteEnv": {
9+
// Allow X11 apps to run inside the container
1310
"DISPLAY": "${localEnv:DISPLAY}"
1411
},
15-
// Add the URLs of features you want added when the container is built.
16-
"features": {
17-
"ghcr.io/devcontainers/features/common-utils:1": {
18-
"username": "none",
19-
"upgradePackages": false
20-
}
21-
},
2212
"customizations": {
2313
"vscode": {
14+
// Set *default* container specific settings.json values on container create.
15+
"settings": {
16+
"python.defaultInterpreterPath": "/venv/bin/python"
17+
},
2418
// Add the IDs of extensions you want installed when the container is created.
2519
"extensions": [
2620
"ms-python.python",
21+
"github.vscode-github-actions",
2722
"tamasfe.even-better-toml",
2823
"redhat.vscode-yaml",
29-
"ryanluker.vscode-coverage-gutters"
24+
"ryanluker.vscode-coverage-gutters",
25+
"charliermarsh.ruff",
26+
"ms-azuretools.vscode-docker"
3027
]
3128
}
3229
},
33-
// Make sure the files we are mapping into the container exist on the host
34-
"initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'",
30+
"features": {
31+
// Some default things like git config
32+
"ghcr.io/devcontainers/features/common-utils:2": {
33+
"upgradePackages": false
34+
}
35+
},
3536
"runArgs": [
37+
// Allow the container to access the host X11 display and EPICS CA
3638
"--net=host",
37-
"--security-opt=label=type:container_runtime_t"
38-
],
39-
"mounts": [
40-
"source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind",
41-
"source=${localEnv:HOME}/.inputrc,target=/root/.inputrc,type=bind",
42-
// map in home directory - not strictly necessary but useful
43-
"source=${localEnv:HOME},target=${localEnv:HOME},type=bind,consistency=cached"
39+
// Make sure SELinux does not disable with access to host filesystems like tmp
40+
"--security-opt=label=disable"
4441
],
45-
// make the workspace folder the same inside and outside of the container
46-
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
47-
"workspaceFolder": "${localWorkspaceFolder}",
42+
// Mount the parent as /workspaces so we can pip install peers as editable
43+
"workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind",
4844
// After the container is created, install the python project in editable form
49-
"postCreateCommand": "pip install -e '.[dev]'"
45+
"postCreateCommand": "pip install $([ -f dev-requirements.txt ] && echo '-c dev-requirements.txt') -e '.[dev]' && pre-commit install"
5046
}

.github/CONTRIBUTING.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Contribute to the project
2+
3+
Contributions and issues are most welcome! All issues and pull requests are
4+
handled through [GitHub](https://github.com/epics-containers/epic-containers.github.io/issues). Also, please check for any existing issues before
5+
filing a new one. If you have a great idea but it involves big changes, please
6+
file a ticket before making a pull request! We want to make sure you don't spend
7+
your time coding something that might not fit the scope of the project.
8+
9+
## Issue or Discussion?
10+
11+
Github also offers [discussions](https://github.com/epics-containers/epic-containers.github.io/discussions) as a place to ask questions and share ideas. If
12+
your issue is open ended and it is not obvious when it can be "closed", please
13+
raise it as a discussion instead.
14+
15+
## Code Coverage
16+
17+
While 100% code coverage does not make a library bug-free, it significantly
18+
reduces the number of easily caught bugs! Please make sure coverage remains the
19+
same or is improved by a pull request!
20+
21+
## Developer Information
22+
23+
It is recommended that developers use a [vscode devcontainer](https://code.visualstudio.com/docs/devcontainers/containers). This repository contains configuration to set up a containerized development environment that suits its own needs.
24+
25+
This project was created using the [Diamond Light Source Copier Template](https://github.com/DiamondLightSource/python-copier-template) for Python projects.
26+
27+
For more information on common tasks like setting up a developer environment, running the tests, and setting a pre-commit hook, see the template's [How-to guides](https://diamondlightsource.github.io/python-copier-template/1.3.0/how-to.html).
Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,34 @@
11
name: Install requirements
2-
description: Run pip install with requirements and upload resulting requirements
2+
description: Install a version of python then call pip install and report what was installed
33
inputs:
4-
requirements_file:
5-
description: Name of requirements file to use and upload
6-
required: true
7-
install_options:
4+
python-version:
5+
description: Python version to install, default is from Dockerfile
6+
default: "dev"
7+
pip-install:
88
description: Parameters to pass to pip install
9-
required: true
10-
python_version:
11-
description: Python version to install
12-
default: "3.x"
9+
default: "$([ -f dev-requirements.txt ] && echo '-c dev-requirements.txt') -e .[dev]"
1310

1411
runs:
1512
using: composite
16-
1713
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
14+
- name: Get version of python
3115
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 }}
16+
PYTHON_VERSION="${{ inputs.python-version }}"
17+
if [ $PYTHON_VERSION == "dev" ]; then
18+
PYTHON_VERSION=$(sed -n "s/ARG PYTHON_VERSION=//p" Dockerfile)
19+
fi
20+
echo "PYTHON_VERSION=$PYTHON_VERSION" >> "$GITHUB_ENV"
3621
shell: bash
3722

38-
- name: Upload lockfiles
39-
uses: actions/upload-artifact@v3
23+
- name: Setup python
24+
uses: actions/setup-python@v5
4025
with:
41-
name: lockfiles
42-
path: lockfiles
26+
python-version: ${{ env.PYTHON_VERSION }}
4327

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
28+
- name: Install packages
29+
run: pip install ${{ inputs.pip-install }}
5730
shell: bash
5831

32+
- name: Report what was installed
33+
run: pip freeze
34+
shell: bash

.github/dependabot.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,16 @@ updates:
99
directory: "/"
1010
schedule:
1111
interval: "weekly"
12+
groups:
13+
actions:
14+
patterns:
15+
- "*"
1216

1317
- package-ecosystem: "pip"
1418
directory: "/"
1519
schedule:
1620
interval: "weekly"
21+
groups:
22+
dev-dependencies:
23+
patterns:
24+
- "*"

.github/pages/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
<link rel="canonical" href="main/index.html">
99
</head>
1010

11-
</html>
11+
</html>

.github/pages/make_switcher.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def get_sorted_tags_list() -> List[str]:
2424
return report_output(stdout, "Tags list")
2525

2626

27-
def get_versions(ref: str, add: Optional[str], remove: Optional[str]) -> List[str]:
27+
def get_versions(ref: str, add: Optional[str]) -> List[str]:
2828
"""Generate the file containing the list of all GitHub Pages builds."""
2929
# Get the directories (i.e. builds) from the GitHub Pages branch
3030
try:
@@ -36,16 +36,13 @@ def get_versions(ref: str, add: Optional[str], remove: Optional[str]) -> List[st
3636
# Add and remove from the list of builds
3737
if add:
3838
builds.add(add)
39-
if remove:
40-
assert remove in builds, f"Build '{remove}' not in {sorted(builds)}"
41-
builds.remove(remove)
4239

4340
# Get a sorted list of tags
4441
tags = get_sorted_tags_list()
4542

4643
# Make the sorted versions list from main branches and tags
4744
versions: List[str] = []
48-
for version in ["dev", "main"] + tags:
45+
for version in ["master", "main"] + tags:
4946
if version in builds:
5047
versions.append(version)
5148
builds.remove(version)
@@ -59,26 +56,22 @@ def get_versions(ref: str, add: Optional[str], remove: Optional[str]) -> List[st
5956
def write_json(path: Path, repository: str, versions: str):
6057
org, repo_name = repository.split("/")
6158
struct = [
62-
dict(version=version, url=f"https://{org}.github.io/{repo_name}/{version}/")
59+
{"version": version, "url": f"https://{org}.github.io/{repo_name}/{version}/"}
6360
for version in versions
6461
]
6562
text = json.dumps(struct, indent=2)
6663
print(f"JSON switcher:\n{text}")
67-
path.write_text(text)
64+
path.write_text(text, encoding="utf-8")
6865

6966

7067
def main(args=None):
7168
parser = ArgumentParser(
72-
description="Make a versions.txt file from gh-pages directories"
69+
description="Make a versions.json file from gh-pages directories"
7370
)
7471
parser.add_argument(
7572
"--add",
7673
help="Add this directory to the list of existing directories",
7774
)
78-
parser.add_argument(
79-
"--remove",
80-
help="Remove this directory from the list of existing directories",
81-
)
8275
parser.add_argument(
8376
"repository",
8477
help="The GitHub org and repository name: ORG/REPO",
@@ -91,7 +84,7 @@ def main(args=None):
9184
args = parser.parse_args(args)
9285

9386
# Write the versions file
94-
versions = get_versions("origin/gh-pages", args.add, args.remove)
87+
versions = get_versions("origin/gh-pages", args.add)
9588
write_json(args.output, args.repository, versions)
9689

9790

.github/workflows/_check.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
on:
2+
workflow_call:
3+
outputs:
4+
branch-pr:
5+
description: The PR number if the branch is in one
6+
value: ${{ jobs.pr.outputs.branch-pr }}
7+
8+
jobs:
9+
pr:
10+
runs-on: "ubuntu-latest"
11+
outputs:
12+
branch-pr: ${{ steps.script.outputs.result }}
13+
steps:
14+
- uses: actions/github-script@v7
15+
id: script
16+
if: github.event_name == 'push'
17+
with:
18+
script: |
19+
const prs = await github.rest.pulls.list({
20+
owner: context.repo.owner,
21+
repo: context.repo.repo,
22+
head: context.repo.owner + ':${{ github.ref_name }}'
23+
})
24+
if (prs.data.length) {
25+
console.log(`::notice ::Skipping CI on branch push as it is already run in PR #${prs.data[0]["number"]}`)
26+
return prs.data[0]["number"]
27+
}

.github/workflows/_dist.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
on:
2+
workflow_call:
3+
4+
jobs:
5+
build:
6+
runs-on: "ubuntu-latest"
7+
8+
steps:
9+
- name: Checkout
10+
uses: actions/checkout@v4
11+
with:
12+
# Need this to get version number from last tag
13+
fetch-depth: 0
14+
15+
- name: Build sdist and wheel
16+
run: >
17+
export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) &&
18+
pipx run build
19+
20+
- name: Upload sdist and wheel as artifacts
21+
uses: actions/upload-artifact@v4
22+
with:
23+
name: dist
24+
path: dist
25+
26+
- name: Check for packaging errors
27+
run: pipx run twine check --strict dist/*
28+
29+
- name: Install produced wheel
30+
uses: ./.github/actions/install_requirements
31+
with:
32+
pip-install: dist/*.whl
33+
34+
- name: Test module --version works using the installed wheel
35+
# If more than one module in src/ replace with module name to test
36+
run: python -m $(ls --hide='*.egg-info' src | head -1) --version

0 commit comments

Comments
 (0)