Skip to content

Commit 9809fb5

Browse files
committed
0 parents  commit 9809fb5

119 files changed

Lines changed: 8093 additions & 0 deletions

File tree

Some content is hidden

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

.ansible-lint

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
skip_list:
2+
- command-instead-of-module

.github/workflows/cicd.yml

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
name: CI/CD
2+
##
3+
# This github workflow is used to run tests on all commits to the develop branch
4+
# to verify all basic processes function correctly.
5+
##
6+
7+
on:
8+
push:
9+
branches:
10+
- master
11+
pull_request:
12+
13+
jobs:
14+
15+
lint:
16+
name: Lint Checks
17+
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
# Shellcheck
23+
# Looks for +x files
24+
- name: ShellCheck
25+
uses: ludeeus/action-shellcheck@master
26+
# with:
27+
# ignore_names: '10_linux'
28+
env:
29+
SHELLCHECK_OPTS: -e SC1091
30+
31+
# Ansible Lint
32+
- name: Run ansible-lint
33+
uses: ansible/ansible-lint@main
34+
with:
35+
working_directory: "test"
36+
37+
# Python Lint
38+
- name: Set Up Python environment
39+
uses: actions/setup-python@v5
40+
with:
41+
python-version: '3.x'
42+
- name: Flake8 Lint
43+
uses: py-actions/flake8@v2
44+
with:
45+
ignore: 'E123,E126,E501,W503,F824'
46+
47+
container:
48+
name: Ansible Tests
49+
needs: [lint]
50+
51+
runs-on: ubuntu-latest
52+
strategy:
53+
matrix:
54+
os: ['debian', 'ubuntu', 'rocky']
55+
steps:
56+
- uses: actions/checkout@v4
57+
58+
- name: Install Dependencies
59+
run: |
60+
sudo apt-get update
61+
sudo apt-get install make podman
62+
63+
- name: Run Container Tests
64+
id: validation_tests
65+
run: make test-${{ matrix.os }}
66+
67+
web_index:
68+
name: Web Index
69+
needs: [lint]
70+
71+
runs-on: ubuntu-latest
72+
steps:
73+
- uses: actions/checkout@v4
74+
with:
75+
submodules: true
76+
fetch-depth: 0
77+
78+
#- name: Pull Submodules (themes)
79+
# run: git submodule update --init --recursive
80+
81+
- name: Install Hugo
82+
uses: peaceiris/actions-hugo@v2
83+
with:
84+
hugo-version: latest
85+
86+
- name: Build Site
87+
run: make web_index/site
88+
89+
- name: Publish Site
90+
uses: peaceiris/actions-gh-pages@v3
91+
if: ${{ github.ref == 'refs/heads/master' }}
92+
with:
93+
github_token: ${{ secrets.GITHUB_TOKEN }}
94+
publish_dir: ./web_index/site
95+
96+
97+
##
98+
# Merge master into release after tests pass
99+
# NOTE: From this point forward, a force push is non-trivial!
100+
##
101+
102+
deploy:
103+
name: Server Release
104+
needs: [lint, container, web_index]
105+
if: github.ref == 'refs/heads/master'
106+
107+
permissions:
108+
pull-requests: write
109+
contents: write
110+
111+
runs-on: ubuntu-latest
112+
steps:
113+
- uses: actions/checkout@v4
114+
with:
115+
fetch-depth: '0'
116+
ref: release
117+
118+
- name: Merge Changes
119+
run: |
120+
git config --local user.email "actions@github.com"
121+
git config --local user.name "Github Actions"
122+
git merge --no-ff "${{ github.sha }}" -m "[CICD-Pass] Merge ${{ github.sha }} into release"
123+
124+
# CICD: master->release
125+
- name: Go Live!
126+
run: |
127+
git push origin release

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Hugo
2+
.hugo_build.lock
3+
/web_index/resources
4+
/web_index/site
5+
6+
# Ansible
7+
.vaultpass
8+
9+
# Python
10+
*.py[cod]
11+
__pycache__
12+
.pytest_cache/
13+
14+
# ./sync
15+
_workspace/

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[submodule "web_index/themes/mainroad"]
2+
path = web_index/themes/mainroad
3+
url = https://github.com/vimux/mainroad.git
4+
[submodule "web_index/themes/aamod"]
5+
path = web_index/themes/aamod
6+
url = https://github.com/recoverysource/aamod.git

LICENSE.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Copyright: 2025 Michael Lustfield (MTecknology)
2+
3+
Redistribution and use in source and binary forms, with or without modification,
4+
are permitted provided that the following conditions are met:
5+
6+
1. Redistributions of source code must retain the above copyright notice, this
7+
list of conditions and the following disclaimer.
8+
9+
2. Redistributions in binary form must reproduce the above copyright notice, this
10+
list of conditions and the following disclaimer in the documentation and/or
11+
other materials provided with the distribution.
12+
13+
3. Neither the name of the copyright holder nor the names of its contributors may
14+
be used to endorse or promote products derived from this software without
15+
specific prior written permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20+
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26+
OF THE POSSIBILITY OF SUCH DAMAGE.

Makefile

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/usr/bin/make -f
2+
##
3+
# Helper functions for Service management.
4+
##
5+
6+
##
7+
# Services - web_index
8+
##
9+
10+
web_index/site: web_index/themes/aamod/theme.toml web_index/themes/mainroad/theme.toml
11+
cd web_index && hugo --minify -d site
12+
13+
%/theme.toml:
14+
git submodule update --init --recursive $*
15+
16+
web_index-browse: web_index/site
17+
cd web_index && sensible-browser site/index.html
18+
19+
web_index-run:
20+
cd web_index && hugo server --disableFastRender
21+
22+
##
23+
# Testing
24+
##
25+
26+
test: test-debian test-ubuntu test-rocky
27+
28+
test-%: tpod_%
29+
podman run --rm -it \
30+
--hostname service01-test \
31+
-v "$(PWD):/srv/ansible" \
32+
tpod_$* /srv/ansible/test/docker/test.sh
33+
34+
35+
##
36+
# Container
37+
##
38+
39+
# Create a container for testing
40+
tpod_%:
41+
podman build -t $@ \
42+
-f test/docker/create.$*
43+
44+
# Log in to a container named "tpod_%"
45+
login-%: tpod_%
46+
podman run --rm -it \
47+
--hostname service01-test \
48+
-v "$(PWD):/srv/ansible" \
49+
tpod_$* /bin/bash
50+
51+
52+
##
53+
# Cleanup
54+
##
55+
56+
# Purge podman and other testing artifacts
57+
clean: cleanpod-tpod_debian cleanpod-tpod_ubuntu cleanpod-tpod_rocky
58+
podman system prune -f
59+
# hugo
60+
$(RM) -r web_index/.hugo_site web_index/resources web_index/site
61+
62+
# Delete a container if it exists
63+
cleanpod-%:
64+
@if [ -n "$(findstring $*,$(shell podman images))" ]; then \
65+
podman rmi $*; \
66+
fi

README.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
Recovery Source: Services
2+
=========================
3+
4+
This repository provides a "standardized" solution to test, deploy, and maintain
5+
various web "services" provided by [Recovery Source](https://handbook.recoverysource.net/).
6+
7+
Basic Workflows
8+
---------------
9+
10+
To Do ...
11+
12+
Repository Structure
13+
--------------------
14+
15+
The structure of this repository:
16+
17+
- ``Makefile``: Convenient helper tasks
18+
- ``data/``: Primary source of data (all known 12-Step groups)
19+
- ``sync/``: Python3 module that collects and re-mangles data
20+
- ``web_index/``: Hugo-based website that hosts https://sober.page
21+
- ``ansible/``: Used for configuration management (deploy, maintain, etc.)
22+
- ``test/``: Data used for automated testing
23+
24+
Web Index
25+
---------
26+
27+
Sober Pages service as a directory services for 12-step focused websites and
28+
aims to provide support for basic maintenance tasks.
29+
30+
See this website running at https://sober.page/.
31+
32+
Source Data
33+
-----------
34+
35+
Everything the Recovery Source project knows about 12-Step groups.
36+
37+
### Data Format
38+
39+
**Location:** ``data/domains/<group>.yaml``
40+
41+
**Format [[YAML](https://handbook.recoverysource.net/essentials/yaml.html)]:**
42+
```
43+
<subdomain>:
44+
title: website title
45+
keywords: list, of, regions
46+
target: <URL>
47+
type: forward OR cname
48+
feed: <type>^<URL>[^<options>]
49+
```
50+
51+
**Required:** subdomain, title, target
52+
53+
**Rules:**
54+
55+
- ``data/domains/*.yaml`` MUST be [valid YAML](https://yaml-online-parser.appspot.com/)
56+
- [``title``, ``keywords``] may be mixed-case, all other fields must be lower-case
57+
- ``target`` should be the shortest functional URL (without
58+
[path/query/fragment](https://handbook.recoverysource.net/essentials/websites.html#url))
59+
- ``target`` should include www if upstream redirects to this address
60+
- ``feed`` may be a [YAML list](https://handbook.recoverysource.net/essentials/yaml.html)
61+
of feed locations (type+url)
62+
- ``subdomain`` is limited to one (1) per ``target``
63+
- ``subdomain`` format should follow ``[type][area]-[district]`` (e.g. aa0-5)
64+
- ``subdomain`` may append characters to resolve conflicts (e.g. aa1-4north)
65+
- ``subdomain`` should use the lowest represented district as canonical
66+
- ``subdomain`` can be used as a SP alias to redirect additional-represented districts
67+
- ``feed/type`` must be one of [``aamod``, ``tsml``]
68+
69+
Sync
70+
----
71+
72+
Data synchronization is done using the ``sync`` python module.
73+
74+
**$ cd services && python3 -m sync -h**:
75+
```
76+
usage: python3 -m sync [-h] [actions] <options>
77+
78+
Synchronize sober.page data with various destinations
79+
80+
options:
81+
-h, --help show this help message and exit
82+
-H <path> Path to source data (hugo format)
83+
-w <path> Local workspace used for importing/caching data
84+
-l <level> Log level (DEBUG, INFO*, WARNING, ERROR)
85+
86+
actions[*]:
87+
-m <path> Generate nginx map file at <path>
88+
-z <zone>:<path> Generate bind9 zone (db) at <path>
89+
90+
[*] At least one script action must be specified.
91+
```

ansible/ansible.cfg

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[defaults]
2+
interpreter_python = /usr/bin/python3
3+
roles_path = roles
4+
vault_password_file = .vaultpass
5+
pipelining = True
6+
localhost_warning=False
7+
8+
[inventory]
9+
inventory_unparsed_warning=False

ansible/group_vars/all/users.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
$ANSIBLE_VAULT;1.1;AES256
2+
63393666313830363662353230376637323363336230633237366330613438343761633233623236
3+
3364386139336661353064636135333231386331336430630a353764666537623935626638663831
4+
64666462626232393134363835663530643565366266386233636637313264636563366435333238
5+
3830623266663166630a643430383562666532636530356630386333313739346164306365323862
6+
62653362643763656531663039303939393038623765363832303831383937613161646531356135
7+
39346363313535376334303364326261343966663564623537663964633562653936663964353963
8+
37303666653263396334646635326363343763383461666564343239383137376130343439353935
9+
37623239613433326135376332313738336133316661316433313561633838373234303966663730
10+
33363539316235306130356338643165643330663663323233656133626639383235346533376437
11+
38343162363930656466346132346237616666373830393164326233323332303639373830663633
12+
39616639396438376433333636386130373938346465613239613865383130386236306262353565
13+
30323862386364396136336561666132363439323365353766356330626264303163316637613366
14+
62363837646535386166666237623364333433653733356461646130663562363662396537323636
15+
65613065326163666637393438613632623836646531316232666466316364303338663832626437
16+
65383331323762386535663763656432373135663562396463363062633766653765323061383036
17+
38333130376137323032393030613232333733313262616664366130653439643637633934613632
18+
36383239323036333230623038663435316533346464306163373865313266373065393964306339
19+
30383536323163316464383536326664636132373664353439656336333639303539326636356136
20+
31633737393430653831626565396332356435616232306339366136643331363539383332663636
21+
36616338386163316235343561623632356338623033623866656561666232393837313961313031
22+
36386332623161353132393333356565663030343130616436393434333337336131653266306430
23+
64613634613465366564623764333037333433663533653234383339656463383233643661613337
24+
63393364616264356531303531313365613863343131366538373537366662613866333437663134
25+
39383938653530316532653666653465383266343833356135636236333135636161376365646161
26+
3065

ansible/maintenance.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
- name: Regular Maintenance
3+
hosts: localhost
4+
vars:
5+
partial_install: "{{ (ansible_is_chroot) or ('container' in ansible_virtualization_tech_guest) }}"
6+
is_server: "{{ not 'pc' in ansible_hostname }}"
7+
is_desktop: "{{ 'pc' in ansible_hostname }}"
8+
is_test: "{{ 'test' in ansible_hostname }}"
9+
roles:
10+
- common
11+
- custom

0 commit comments

Comments
 (0)