Skip to content

Commit 3dde0c0

Browse files
committed
Create nginx redirect map for Confluence URLs from sitemap.xml
nginx has a _very_ fast map implementation that allows you to provide a map of old->new redirect URLs. Rather than us having to maintain a list of old/broken links in mkdocs.yml, we now create a redirect map from the sitemap.xml file mkdocs already creates. The downloads server that handles the redirects from wiki.asterisk.org to docs.asterisk.org now uses that map to do the redirects. Also moved the files in the utils directory that were only needed for the initial import to the utils/initial_import directory.
1 parent 3b592f6 commit 3dde0c0

File tree

10 files changed

+109
-18
lines changed

10 files changed

+109
-18
lines changed

.github/workflows/publish.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@ jobs:
1515
- uses: actions/checkout@v4
1616
with:
1717
fetch-depth: 0
18+
1819
- uses: actions/setup-python@v5
1920
with:
2021
python-version: 3.x
2122
cache: 'pip'
22-
- run: pip install -r requirements.txt
23-
23+
24+
- name: Setup
25+
run: |
26+
pip install -r requirements.txt
27+
2428
- name: Get Token needed to push updates
2529
id: get_workflow_token
2630
uses: peter-murray/workflow-application-token-action@v3
@@ -35,11 +39,11 @@ jobs:
3539
GH_TOKEN: ${{steps.get_workflow_token.outputs.token}}
3640
run: |
3741
gh auth setup-git -h github.com
38-
git config --global user.email "asteriskteam@digium.com"
42+
git config --global user.email "asteriskteam@sangoma.com"
3943
git config --global user.name "Asterisk Development Team"
4044
cat >Makefile.inc <<EOF
4145
${{vars.MAKEFILE_INC}}
4246
EOF
4347
make
48+
make temp/site/redirect_map.conf
4449
make deploy
45-

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ else
180180
@mkdocs build -f $(BUILD_DIR)/mkdocs.yml -d $(SITE_DIR)
181181
endif
182182

183+
temp/site/redirect_map.conf: temp/site/sitemap.xml
184+
@echo "Creating $@ from $^"
185+
@./utils/create_redirect_map.py $^ $@
186+
183187
deploy: no-branch-check
184188
@if [ -z "$(DEPLOY_REMOTE)" ] ; then \
185189
echo "No DEPLOY_REMOTE was defined in Makefile.inc" ;\
@@ -189,7 +193,7 @@ deploy: no-branch-check
189193
@[ ! -f $(BUILD_DIR)/mkdocs.yml ] && \
190194
{ echo "Can't deploy. '$(BUILD_DIR)/mkdocs.yml' not found" ; exit 1 ; } || :
191195
@sed -i -r -e "$(MINIFY_REGEX)" $(BUILD_DIR)/mkdocs.yml
192-
@mkdocs gh-deploy -r $(DEPLOY_REMOTE) -b $(DEPLOY_BRANCH) \
196+
@mkdocs gh-deploy --dirty -r $(DEPLOY_REMOTE) -b $(DEPLOY_BRANCH) \
193197
-d $(SITE_DIR) --no-history -f $(BUILD_DIR)/mkdocs.yml
194198

195199
serve:

mkdocs.yml

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,6 @@ extra_css:
5656
- material-override.css
5757

5858
plugins:
59-
- redirects:
60-
redirect_maps:
61-
Asterisk+Community+Code+of+Conduct.md: Asterisk-Community/Asterisk-Community-Code-of-Conduct.md
62-
Building+and+Installing+Asterisk.md: Getting-Started/Installing-Asterisk/Installing-Asterisk-From-Source/Building-and-Installing-Asterisk.md
63-
Secure+Calling+Tutorial.md: Deployment/Secure-Calling/Secure-Calling-Tutorial/index.md
64-
PJSIP+Configuration+Wizard.md: Configuration/Channel-Drivers/SIP/Configuring-res_pjsip/PJSIP-Configuration-Wizard.md
65-
Realtime+Database+Configuration.md: Fundamentals/Asterisk-Configuration/Database-Support-Configuration/Realtime-Database-Configuration.md
66-
ConfBridge.md: Configuration/Applications/Conferencing-Applications/ConfBridge/index.md
67-
SIP+Retransmissions.md: Deployment/Troubleshooting/SIP-Retransmissions.md
68-
Voice+Prompts+and+Music+on+Hold+License.md: About-the-Project/License-Information/Voice-Prompts-and-Music-on-Hold-License.md
69-
Querying+and+Manipulating+State.md: Fundamentals/Key-Concepts/States-and-Presence/Querying-and-Manipulating-State.md
70-
Build+System+Architecture.md: Development/Reference-Information/Other-Reference-Information/Build-System-Architecture.md
71-
Important+Security+Considerations.md: Deployment/Important-Security-Considerations/index.md
7259
- search
7360
- awesome-pages:
7461
filename: .pages

utils/create_redirect_map.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/usr/bin/env python3
2+
"""Convert sitemap to redirect map for old Confluence URLs
3+
4+
Copyright (C) 2025, Sangoma Technologies, Inc.
5+
George T Joseph <gjoseph@sangoma.com>
6+
7+
This program is free software, distributed under the terms of
8+
the GNU General Public License Version 2.
9+
"""
10+
11+
import sys, os, re
12+
import xml.etree.ElementTree as ET
13+
from urllib.parse import urlparse
14+
from datetime import datetime as dt
15+
import datetime
16+
17+
sectionmap = {
18+
"WhatsNew/" : "New+in+{version}",
19+
"Upgrading/" : "Upgrading+to+Asterisk+{version}",
20+
"API_Documentation/" : "Asterisk+{version}+Command+Reference",
21+
}
22+
23+
subsectionmap = {
24+
"AGI_Commands/": ("AGI+Commands", "AGICommand"),
25+
"AMI_Actions/": ("AMI+Actions", "ManagerAction"),
26+
"AMI_Events/": ("AMI+Events", "ManagerEvent"),
27+
"Dialplan_Applications/": ("Dialplan+Applications", "Application"),
28+
"Dialplan_Functions/": ("Dialplan+Functions", "Function"),
29+
"ARI/": ("ARI", None),
30+
"Asterisk_REST_Interface/": ("ARI", None),
31+
"Module_Configuration/": ("Module+Configuration", "Configuration"),
32+
"Modules/": (None, None),
33+
}
34+
35+
def main(argv):
36+
infile = argv[1] if len(argv) > 1 else None
37+
outfile = argv[2] if len(argv) > 2 else None
38+
tree = ET.parse(infile)
39+
redirects = {}
40+
for loc in tree.findall(".//{*}url/{*}loc"):
41+
url = urlparse(loc.text)
42+
path = url.path
43+
if path.endswith('/'):
44+
path = path[:-1]
45+
m = re.match(r'/Asterisk_([0-9]+)_Documentation/([^/]+/)?([^/]+/)?([^/]+/)?$', url.path)
46+
api_section = ""
47+
section = ""
48+
pagename = ""
49+
if m is not None:
50+
version = m.groups()[0]
51+
if m.groups()[1]:
52+
section = sectionmap[m.groups()[1]]
53+
if m.groups()[2]:
54+
subsection = subsectionmap[m.groups()[2]]
55+
pagename = m.groups()[3]
56+
if m.lastindex == 1:
57+
key = f"/wiki/display/AST/Asterisk+{version}+Documentation".lower()
58+
elif m.lastindex == 2:
59+
key = f"/wiki/display/AST/{section.format(version=version)}".lower()
60+
elif m.lastindex == 3:
61+
if subsection[0] is None:
62+
continue
63+
key = f"/wiki/display/AST/Asterisk+{version}+{subsection[0]}".lower()
64+
elif m.lastindex == 4:
65+
if pagename.endswith('/'):
66+
pagename = pagename[:-1]
67+
if subsection[1] is None:
68+
sn = ""
69+
pagename = pagename.replace('_','+')
70+
else:
71+
sn = subsection[1]+"_"
72+
if subsection[1] == "AGICommand":
73+
pagename = pagename.replace('_','+')
74+
key = f"/wiki/display/AST/Asterisk+{version}+{sn}{pagename}".lower()
75+
else:
76+
if re.match(r'/(?:Certified-Asterisk|Latest_API)', url.path):
77+
continue
78+
if url.path == '/':
79+
key = "/wiki/display/AST/Home".lower()
80+
else:
81+
key = f"/wiki/display/AST/{os.path.basename(path).replace('-','+')}".lower()
82+
if key not in redirects:
83+
redirects[key] = url.path
84+
with open(outfile, 'w') if outfile else sys.stdout as f:
85+
f.write("# Auto-generated file. Do not edit!\n")
86+
d = dt.now().strftime("%Y-%m-%d %T %z")
87+
f.write(f"# Generated {d}\n")
88+
f.write("# Maps old URLs to new URLs\n")
89+
f.write("# Format: /old/url/ /new/url/;\n")
90+
f.write("#\n")
91+
for k in redirects.keys():
92+
f.write(f"{k} {redirects[k]};\n")
93+
return 0
94+
95+
if __name__ == "__main__":
96+
sys.exit(main(sys.argv) or 0)

0 commit comments

Comments
 (0)