Skip to content

Commit e5920fc

Browse files
authored
Merge pull request #10 from epics-containers/dev
Major Overhaul
2 parents 87b86ec + 15448d7 commit e5920fc

File tree

105 files changed

+2516
-1463
lines changed

Some content is hidden

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

105 files changed

+2516
-1463
lines changed

.devcontainer/devcontainer.json

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// For format details, see https://containers.dev/implementors/json_reference/
2+
{
3+
"name": "Python 3 Developer Container",
4+
"build": {
5+
"dockerfile": "../Dockerfile",
6+
"target": "build",
7+
// Only upgrade pip, we will install the project below
8+
"args": {
9+
"PIP_OPTIONS": "--upgrade pip"
10+
}
11+
},
12+
"remoteEnv": {
13+
"DISPLAY": "${localEnv:DISPLAY}"
14+
},
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+
},
22+
// Set *default* container specific settings.json values on container create.
23+
"settings": {
24+
"python.defaultInterpreterPath": "/venv/bin/python"
25+
},
26+
"customizations": {
27+
"vscode": {
28+
// Add the IDs of extensions you want installed when the container is created.
29+
"extensions": [
30+
"ms-python.python",
31+
"tamasfe.even-better-toml",
32+
"redhat.vscode-yaml",
33+
"ryanluker.vscode-coverage-gutters"
34+
]
35+
}
36+
},
37+
// Make sure the files we are mapping into the container exist on the host
38+
"initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'",
39+
"runArgs": [
40+
"--net=host",
41+
"--security-opt=label=type:container_runtime_t"
42+
],
43+
"mounts": [
44+
"source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind",
45+
"source=${localEnv:HOME}/.inputrc,target=/root/.inputrc,type=bind",
46+
// map in home directory - not strictly necessary but useful
47+
"source=${localEnv:HOME},target=${localEnv:HOME},type=bind,consistency=cached"
48+
],
49+
// make the workspace folder the same inside and outside of the container
50+
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
51+
"workspaceFolder": "${localWorkspaceFolder}",
52+
// After the container is created, install the python project in editable form
53+
"postCreateCommand": "pip install -e '.[dev]'"
54+
}

.github/CONTRIBUTING.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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/epics-containers/epics-containers.github.io/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/epics-containers/epics-containers.github.io/discussions
20+
21+
22+
Developer guide
23+
---------------
24+
25+
The `Developer Guide`_ contains information on setting up a development
26+
environment, building docs and what standards the documentation
27+
should follow.
28+
29+
.. _Developer Guide: https://diamondlightsource.github.io/epics-containers.github.io/main/developer/how-to/contribute.html
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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.x"
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
58+

.github/dependabot.yml

Lines changed: 16 additions & 0 deletions
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/index.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<!DOCTYPE html>
22
<html>
3-
<head>
4-
<title>Redirecting to master branch</title>
3+
4+
<head>
5+
<title>Redirecting to main branch</title>
56
<meta charset="utf-8">
67
<meta http-equiv="refresh" content="0; url=./main/index.html">
78
<link rel="canonical" href="main/index.html">
8-
</head>
9+
</head>
10+
911
</html>

.github/pages/make_switcher.py

Lines changed: 99 additions & 0 deletions
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()

.github/workflows/docs.yml

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,49 @@ on:
55
pull_request:
66

77
jobs:
8-
build:
9-
name: "Docs CI"
8+
docs:
9+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
1010
runs-on: ubuntu-latest
1111

1212
steps:
13-
- name: Checkout Source
14-
uses: actions/checkout@v2
13+
- name: Avoid git conflicts when tag and branch pushed at same time
14+
if: startsWith(github.ref, 'refs/tags')
15+
run: sleep 60
16+
17+
- name: Checkout
18+
uses: actions/checkout@v3
1519
with:
16-
# require history to get back to last tag for version number of branches
20+
# Need this to get version number from last tag
1721
fetch-depth: 0
18-
submodules: true
1922

20-
- name: Set up Python
21-
uses: actions/setup-python@v2
23+
- name: Install system packages
24+
# Can delete this if you don't use graphviz in your docs
25+
run: sudo apt-get install graphviz
26+
27+
- name: Install python packages
28+
uses: ./.github/actions/install_requirements
2229
with:
23-
python-version: "3.7"
30+
requirements_file: requirements-dev-3.x.txt
31+
install_options: -e .[dev]
2432

25-
- name: Install Python Dependencies
26-
run: |
27-
pip install pipenv
28-
pipenv install --dev --deploy --python $(which python) && pipenv graph
29-
- name: Build Docs
30-
run: pipenv run docs
33+
- name: Build docs
34+
run: tox -e docs
35+
36+
- name: Sanitize ref name for docs version
37+
run: echo "DOCS_VERSION=${GITHUB_REF_NAME//[^A-Za-z0-9._-]/_}" >> $GITHUB_ENV
3138

3239
- name: Move to versioned directory
33-
# e.g. main or 0.1.2
34-
run: mv build/html ".github/pages/${GITHUB_REF##*/}"
40+
run: mv build/html .github/pages/$DOCS_VERSION
41+
42+
- name: Write switcher.json
43+
run: python .github/pages/make_switcher.py --add $DOCS_VERSION ${{ github.repository }} .github/pages/switcher.json
3544

3645
- name: Publish Docs to gh-pages
37-
# Only main and tags are published
38-
if: "${{ github.repository_owner == 'epics-containers' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags')) }}"
46+
if: github.event_name == 'push' && github.actor != 'dependabot[bot]'
3947
# We pin to the SHA, not the tag, for security reasons.
4048
# https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
41-
uses: peaceiris/actions-gh-pages@bbdfb200618d235585ad98e965f4aafc39b4c501 # v3.7.3
49+
uses: peaceiris/actions-gh-pages@64b46b4226a4a12da2239ba3ea5aa73e3163c75b # v3.9.1
4250
with:
4351
github_token: ${{ secrets.GITHUB_TOKEN }}
4452
publish_dir: .github/pages
45-
keep_files: true
53+
keep_files: true

.github/workflows/docs_clean.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Docs Cleanup CI
2+
3+
# delete branch documentation when a branch is deleted
4+
# also allow manually deleting a documentation version
5+
on:
6+
delete:
7+
workflow_dispatch:
8+
inputs:
9+
version:
10+
description: "documentation version to DELETE"
11+
required: true
12+
type: string
13+
14+
jobs:
15+
remove:
16+
if: github.event.ref_type == 'branch' || github.event_name == 'workflow_dispatch'
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v3
22+
with:
23+
ref: gh-pages
24+
25+
- name: removing documentation for branch ${{ github.event.ref }}
26+
if: ${{ github.event_name != 'workflow_dispatch' }}
27+
run: echo "REF_NAME=${{ github.event.ref }}" >> $GITHUB_ENV
28+
29+
- name: manually removing documentation version ${{ github.event.inputs.version }}
30+
if: ${{ github.event_name == 'workflow_dispatch' }}
31+
run: echo "REF_NAME=${{ github.event.inputs.version }}" >> $GITHUB_ENV
32+
33+
- name: Sanitize ref name for docs version
34+
run: echo "DOCS_VERSION=${REF_NAME//[^A-Za-z0-9._-]/_}" >> $GITHUB_ENV
35+
36+
- name: update index and push changes
37+
run: |
38+
rm -r $DOCS_VERSION
39+
python make_switcher.py --remove $DOCS_VERSION ${{ github.repository }} switcher.json
40+
git config --global user.name 'GitHub Actions Docs Cleanup CI'
41+
git config --global user.email '[email protected]'
42+
git commit -am "Removing redundant docs version $DOCS_VERSION"
43+
git push

0 commit comments

Comments
 (0)