diff --git a/NEWS b/NEWS index b260a067..ceee7d7b 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +1.8.14.dev0 + * Add a recent contributors section to the documentation, because credit where credit's due! See: + https://torsion.org/borgmatic/#recent-contributors + 1.8.13 * #298: Add "delete" and "rdelete" actions to delete archives or entire repositories. * #785: Add an "only_run_on" option to consistency checks so you can limit a check to running on diff --git a/README.md b/README.md index 82684d8a..a7000d68 100644 --- a/README.md +++ b/README.md @@ -155,3 +155,7 @@ general, contributions are very welcome. We don't bite! Also, please check out the [borgmatic development how-to](https://torsion.org/borgmatic/docs/how-to/develop-on-borgmatic/) for info on cloning source code, running tests, etc. + +### Recent contributors + +{% include borgmatic/contributors.html %} diff --git a/docs/Dockerfile b/docs/Dockerfile index bf82c96a..ae4d7ead 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,14 +1,15 @@ -FROM docker.io/alpine:3.17.1 as borgmatic +FROM docker.io/alpine:3.20.1 AS borgmatic COPY . /app -RUN apk add --no-cache py3-pip py3-ruamel.yaml py3-ruamel.yaml.clib -RUN pip install --no-cache /app && generate-borgmatic-config && chmod +r /etc/borgmatic/config.yaml +RUN apk add --no-cache py3-pip py3-requests py3-ruamel.yaml py3-ruamel.yaml.clib +RUN pip install --break-system-packages --no-cache /app && generate-borgmatic-config && chmod +r /etc/borgmatic/config.yaml RUN borgmatic --help > /command-line.txt \ && for action in rcreate transfer create prune compact check delete extract config "config bootstrap" "config generate" "config validate" export-tar mount umount rdelete restore rlist list rinfo info break-lock borg; do \ echo -e "\n--------------------------------------------------------------------------------\n" >> /command-line.txt \ && borgmatic $action --help >> /command-line.txt; done +RUN /app/docs/fetch-contributors >> /contributors.html -FROM docker.io/node:19.5.0-alpine as html +FROM docker.io/node:22.4.0-alpine AS html ARG ENVIRONMENT=production @@ -24,11 +25,12 @@ RUN npm install @11ty/eleventy \ markdown-it-replace-link COPY --from=borgmatic /etc/borgmatic/config.yaml /source/docs/_includes/borgmatic/config.yaml COPY --from=borgmatic /command-line.txt /source/docs/_includes/borgmatic/command-line.txt +COPY --from=borgmatic /contributors.html /source/docs/_includes/borgmatic/contributors.html COPY . /source RUN NODE_ENV=${ENVIRONMENT} npx eleventy --input=/source/docs --output=/output/docs \ && mv /output/docs/index.html /output/index.html -FROM docker.io/nginx:1.22.1-alpine +FROM docker.io/nginx:1.26.1-alpine COPY --from=html /output /usr/share/nginx/html COPY --from=borgmatic /etc/borgmatic/config.yaml /usr/share/nginx/html/docs/reference/config.yaml diff --git a/docs/fetch-contributors b/docs/fetch-contributors new file mode 100755 index 00000000..66b984ed --- /dev/null +++ b/docs/fetch-contributors @@ -0,0 +1,68 @@ +#!/usr/bin/python + +''' +A script to fetch recent contributors to borgmatic, used during documentation generation. +''' + +import datetime +import itertools +import operator +import subprocess + +import requests + + +def list_merged_pulls(url): + ''' + Given a Gitea or GitHub API endpoint URL for pull requests, fetch and return the corresponding + JSON for all such merged pull requests. + ''' + response = requests.get(f'{url}?state=closed', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}) + + if not response.ok: + response.raise_for_status() + + return tuple(pull for pull in response.json() if pull.get('merged_at')) + + +API_ENDPOINT_URLS = ( + 'https://projects.torsion.org/api/v1/repos/borgmatic-collective/borgmatic/pulls', + 'https://api.github.com/repos/borgmatic-collective/borgmatic/pulls', +) +RECENT_CONTRIBUTORS_CUTOFF_DAYS = 365 + + +def print_contributors(): + ''' + Display the recent contributors as a row of avatars in an HTML fragment. + ''' + pulls = tuple(itertools.chain.from_iterable(list_merged_pulls(url) for url in API_ENDPOINT_URLS)) + seen_user_ids = set() + + print('

') + + for pull in sorted(pulls, key=operator.itemgetter('merged_at'), reverse=True): + merged_at = pull.get('merged_at') + user = pull.get('user') + + if not merged_at or not user: + continue + + user_id = user.get('id') + + if not user_id or user_id in seen_user_ids: + continue + + if datetime.datetime.fromisoformat(merged_at) < datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=RECENT_CONTRIBUTORS_CUTOFF_DAYS): + continue + + seen_user_ids.add(user_id) + print( + f'''''' + ) + + print('

') + + +if __name__ == '__main__': + print_contributors() diff --git a/setup.py b/setup.py index 73eec2d9..da133ece 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import find_packages, setup -VERSION = '1.8.13' +VERSION = '1.8.14.dev0' setup(