Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: pre-commit

on:
push:
branches:
- main
pull_request:

jobs:
pre-commit:
name: Run pre-commit hooks
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'

- uses: pre-commit/action@v3.0.1
17 changes: 17 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.1
hooks:
- id: ruff
args: [--fix]
- id: ruff-format

- repo: local
hooks:
- id: ty
name: ty
entry: ty check --ignore unresolved-import
language: python
additional_dependencies: [ty==0.0.17]
types_or: [python, pyi]
pass_filenames: false
85 changes: 47 additions & 38 deletions src/starterkit_ci/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
__all__ = [
'parse_args',
'sphinx_config',
"parse_args",
"sphinx_config",
]

import argparse
Expand All @@ -11,72 +11,81 @@

from . import sphinx_config

SOURCE_DIR = '.'
BUILD_DIR = 'build'
SOURCE_DIR = "."
BUILD_DIR = "build"


def parse_args():
known_commands = {
'clean': clean_docs,
'build': build_docs,
'check': check_docs,
'deploy': deploy_docs,
"clean": clean_docs,
"build": build_docs,
"check": check_docs,
"deploy": deploy_docs,
}

parser = argparse.ArgumentParser()
parser.add_argument('command', choices=known_commands)
parser.add_argument('--source-dir', required=False, default=os.getcwd())
parser.add_argument('--allow-warnings', action='store_true')
parser.add_argument("command", choices=known_commands)
parser.add_argument("--source-dir", required=False, default=os.getcwd())
parser.add_argument("--allow-warnings", action="store_true")

args = parser.parse_args()

known_commands[args.command](
source_dir=args.source_dir,
allow_warnings=args.allow_warnings
source_dir=args.source_dir, allow_warnings=args.allow_warnings
)


def clean_docs(source_dir, allow_warnings=False):
_sphinx_build('clean', source_dir, allow_warnings)
_sphinx_build("clean", source_dir, allow_warnings)


def build_docs(source_dir, allow_warnings=False):
_sphinx_build('html', source_dir, allow_warnings)
_sphinx_build("html", source_dir, allow_warnings)


def check_docs(source_dir, allow_warnings=False):
_sphinx_build('linkcheck', source_dir, allow_warnings)
_sphinx_build("linkcheck", source_dir, allow_warnings)


def deploy_docs(source_dir, allow_warnings=False):
if os.environ['TRAVIS_BRANCH'] != 'master':
print('This commit was made against', os.environ['TRAVIS_BRANCH'],
'and not the master! No deploy!')
if os.environ["TRAVIS_BRANCH"] != "master":
print(
"This commit was made against",
os.environ["TRAVIS_BRANCH"],
"and not the master! No deploy!",
)
return

built_dir = join(source_dir, BUILD_DIR, 'html')
git_rev = check_output(['git', 'rev-parse', '--short', 'HEAD'],
cwd=source_dir, universal_newlines=True)
shutil.copy(join(source_dir, SOURCE_DIR, '.nojekyll'), built_dir)

check_call(['git', 'init'], cwd=built_dir)
check_call(['git', 'config', 'user.name', 'Alex Pearce'], cwd=built_dir)
check_call(['git', 'config', 'user.email', 'alex@alexpearce.me'], cwd=built_dir)

push_url = 'https://' + os.environ['GH_TOKEN'] + '@github.com/' + os.environ['TRAVIS_REPO_SLUG'] + '.git'
check_call(['git', 'remote', 'add', 'upstream', push_url], cwd=built_dir)
check_call(['git', 'fetch', 'upstream'], cwd=built_dir)
check_call(['git', 'reset', 'upstream/gh-pages'], cwd=built_dir)
built_dir = join(source_dir, BUILD_DIR, "html")
git_rev = check_output(
["git", "rev-parse", "--short", "HEAD"], cwd=source_dir, universal_newlines=True
)
shutil.copy(join(source_dir, SOURCE_DIR, ".nojekyll"), built_dir)

check_call(["git", "init"], cwd=built_dir)
check_call(["git", "config", "user.name", "Alex Pearce"], cwd=built_dir)
check_call(["git", "config", "user.email", "alex@alexpearce.me"], cwd=built_dir)

push_url = (
"https://"
+ os.environ["GH_TOKEN"]
+ "@github.com/"
+ os.environ["TRAVIS_REPO_SLUG"]
+ ".git"
)
check_call(["git", "remote", "add", "upstream", push_url], cwd=built_dir)
check_call(["git", "fetch", "upstream"], cwd=built_dir)
check_call(["git", "reset", "upstream/gh-pages"], cwd=built_dir)

check_call(['touch', '.'], cwd=built_dir)
check_call(["touch", "."], cwd=built_dir)

check_call(['git', 'add', '-A', '.'], cwd=built_dir)
check_call(['git', 'commit', '-m', 'Rebuild pages at ' + git_rev], cwd=built_dir)
check_call(['git', 'push', '-q', 'upstream', 'HEAD:gh-pages'], cwd=built_dir)
check_call(["git", "add", "-A", "."], cwd=built_dir)
check_call(["git", "commit", "-m", "Rebuild pages at " + git_rev], cwd=built_dir)
check_call(["git", "push", "-q", "upstream", "HEAD:gh-pages"], cwd=built_dir)


def _sphinx_build(cmd, source_dir, allow_warnings):
cmd = ['sphinx-build', '-M', cmd, SOURCE_DIR, BUILD_DIR]
cmd = ["sphinx-build", "-M", cmd, SOURCE_DIR, BUILD_DIR]
if not allow_warnings:
cmd += ['-W']
cmd += ["-W"]
return check_call(cmd, cwd=source_dir)
4 changes: 2 additions & 2 deletions src/starterkit_ci/sphinx_config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
def setup(app):
fix_markdown_file_downloads.configure_app(app)
panels.configure_app(app)
for extra_setup_func in setup.extra_setup_funcs:
for extra_setup_func in setup.extra_setup_funcs: # type: ignore[attr-defined]
extra_setup_func(app)

# Create redirects
Expand All @@ -96,4 +96,4 @@ def setup(app):


# Allow additional setup functions to be defined in projects
setup.extra_setup_funcs = []
setup.extra_setup_funcs = [] # type: ignore[attr-defined]
14 changes: 9 additions & 5 deletions src/starterkit_ci/sphinx_config/fix_markdown_file_downloads.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
__all__ = [
'configure_app',
'FixMarkdownDownloads',
"configure_app",
"FixMarkdownDownloads",
]

from os.path import isfile, join, dirname
Expand All @@ -19,9 +19,13 @@ class FixMarkdownDownloads(SphinxTransform):

def apply(self, **kwargs):
for old_node in self.document.traverse(pending_xref):
if not isfile(join(dirname(old_node.source), old_node['reftarget'])):
if not isfile(join(dirname(old_node.source), old_node["reftarget"])):
continue
node1 = nodes.literal('', '', *old_node.children[0].children, classes=['xref', 'download'])
node1 = nodes.literal(
"", "", *old_node.children[0].children, classes=["xref", "download"]
)
old_node.replace(old_node.children[0], node1)
new_node = download_reference(old_node.rawsource, '', *old_node.children, **old_node.attributes)
new_node = download_reference(
old_node.rawsource, "", *old_node.children, **old_node.attributes
)
old_node.parent.replace(old_node, new_node)
63 changes: 38 additions & 25 deletions src/starterkit_ci/sphinx_config/panels.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
__all__ = [
'configure_app',
'AddPanels',
"configure_app",
"AddPanels",
]

import re
Expand All @@ -11,23 +11,23 @@

def configure_app(app):
app.add_transform(AddPanels)
app.add_css_file('panels.css')
app.add_js_file('panels.js')
app.add_css_file("panels.css")
app.add_js_file("panels.js")


class AddPanels(SphinxTransform):
default_priority = 10

# Mapping of name -> (default_visibile, icon)
panel_defaults = {
'prereq': (True, 'rocket'),
'callout': (True, 'info-circle'),
'challenge': (True, 'square-o'),
'hiddenchallenge': (False, 'square-o'),
'solution': (False, 'check-square-o'),
'objectives': (True, 'line-chart'),
'keypoints': (True, 'key'),
'discussion': (False, 'bell'),
"prereq": (True, "rocket"),
"callout": (True, "info-circle"),
"challenge": (True, "square-o"),
"hiddenchallenge": (False, "square-o"),
"solution": (False, "check-square-o"),
"objectives": (True, "line-chart"),
"keypoints": (True, "key"),
"discussion": (False, "bell"),
}

def apply(self, **kwargs):
Expand All @@ -38,46 +38,59 @@ def apply(self, **kwargs):
try:
visibile, icon = self.panel_defaults[panel_type]
except KeyError:
raise ValueError(f'Unrecognised panel type {panel_type}',
self.panel_defaults.keys())
raise ValueError(
f"Unrecognised panel type {panel_type}",
self.panel_defaults.keys(),
)

# Find the body of the panel
inner_node = node
current_nodes = []
while True:
inner_node = inner_node.next_node(descend=False, siblings=True, ascend=False)
inner_node = inner_node.next_node(
descend=False, siblings=True, ascend=False
)
if inner_node is None:
raise ValueError(f'Failed to find end block for {node.rawsource} in {node.source}')
match = re.match(r'^ *{%\s*(\w+)\s*"([^"]+)"\s*%} *$', node.rawsource)
raise ValueError(
f"Failed to find end block for {node.rawsource} in {node.source}"
)
match = re.match(
r'^ *{%\s*(\w+)\s*"([^"]+)"\s*%} *$', node.rawsource
)
# Check if we're at the end of the panel block
if re.match(r'^\s*{%\s*end' + panel_type + r'\s*%}\s*$', inner_node.rawsource):
if re.match(
r"^\s*{%\s*end" + panel_type + r"\s*%}\s*$",
inner_node.rawsource,
):
inner_node.parent.remove(inner_node)
break
current_nodes.append(inner_node)

# Create a div
panel_body = nodes.container()
panel_body.attributes['classes'].append('panel-body')
panel_body.attributes["classes"].append("panel-body")
for inner_node in current_nodes:
inner_node.parent.remove(inner_node)
panel_body.append(inner_node)

# Create the title text
header_text = nodes.paragraph(ids=[title.replace(' ', '-').lower()])
header_text.append(nodes.raw('', f'<i class="fa fa-{icon}"></i> ', format='html'))
header_text = nodes.paragraph(ids=[title.replace(" ", "-").lower()])
header_text.append(
nodes.raw("", f'<i class="fa fa-{icon}"></i> ', format="html")
)
header_text.append(nodes.Text(title))

# Create the title bar
header = nodes.container()
header.attributes['classes'].append('panel-header')
header.attributes["classes"].append("panel-header")
if visibile:
header.attributes['classes'].append('open')
header.attributes["classes"].append("open")
header.append(header_text)

# Move the inner nodes to the new container node and replace the parent
new_node = nodes.container()
new_node.attributes['classes'].append('panel')
new_node.attributes['classes'].append('panel-' + panel_type)
new_node.attributes["classes"].append("panel")
new_node.attributes["classes"].append("panel-" + panel_type)
new_node.append(panel_body)
new_node.insert(0, header)
node.parent.replace(node, new_node)