1
+ name : redisvl_docs_sync
2
+
3
+ on :
4
+ schedule :
5
+ - cron : ' 0 0 * * *' # run every day at midnight UTC time
6
+ workflow_dispatch : # or run on manual trigger
7
+
8
+ jobs :
9
+ redisvl_docs_sync :
10
+ runs-on : ubuntu-latest
11
+ permissions :
12
+ contents : write
13
+ pull-requests : write
14
+ actions : write
15
+ steps :
16
+ - name : ' Checkout'
17
+ uses : ' actions/checkout@v3'
18
+
19
+ - name : ' Install deps'
20
+ run : |
21
+ pip3 install -U sphinx
22
+ pip3 install sphinx_design sphinx_copybutton nbsphinx sphinx_favicon myst_nb sphinx_markdown_builder==0.6.8 jupyter
23
+
24
+ - name : ' Fetch redisvl repo'
25
+ run : |
26
+ git clone https://github.com/redis/redis-vl-python
27
+
28
+ - name : ' Run sphinx-build'
29
+ id : ' sphinx'
30
+ env :
31
+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
32
+ run : |
33
+ pushd redis-vl-python
34
+
35
+ # Get latest release
36
+ latest_release=$(gh release -R redis/redis-vl-python list --json name,isLatest --jq '.[] | select(.isLatest)|.name')
37
+ git checkout "tags/${latest_release}"
38
+ pip3 install -e .
39
+
40
+ popd
41
+ sphinx-build -M markdown ./redis-vl-python/docs ./build
42
+
43
+ echo "release=${latest_release}" >> "$GITHUB_OUTPUT"
44
+
45
+ - name : ' Format markdown files for hugo compatibility'
46
+ run : |
47
+ #!/bin/bash
48
+ mkdir -p redis_vl_hugo/user_guide/
49
+ mkdir redis_vl_hugo/overview/
50
+ mkdir redis_vl_hugo/api/
51
+
52
+ function format() {
53
+ src=$1
54
+
55
+ # Extract title from source file
56
+ title=$(head -n 1 ${src} | sed 's/# //')
57
+ linkTitle="${title}"
58
+
59
+ # All words except first should be lowercased in linkTitle, except for RedisVL, API, CLI, LLMs, JSON
60
+ if [[ "$linkTitle" =~ \ ]]; then
61
+ linkTitle=$(awk '{ $1=$1; for (i=2; i<=NF; i++) if ($i != "RedisVL" && $i != "API" && $i != "CLI" && $i != "LLMs" && $i != "JSON") $i=tolower($i); print }' <<< "${linkTitle}")
62
+ fi
63
+
64
+ # Inject frontmatter in destination file
65
+ cat >_tmp <<EOL
66
+ ---
67
+ linkTitle: ${linkTitle}
68
+ title: ${title}
69
+ type: integration
70
+ EOL
71
+
72
+ # Inject weight property for index pages to preserve order
73
+ case "${title}" in
74
+ "Overview")
75
+ echo "weight: 3" >> _tmp ;;
76
+ "User Guides")
77
+ echo "weight: 4" >> _tmp ;;
78
+ "RedisVL API")
79
+ echo "weight: 5" >> _tmp ;;
80
+ esac
81
+
82
+ # For user guides, strip the leading numbers from filename and use them for weight
83
+ f=$(basename "${src}")
84
+ if [[ "$f" =~ ^([0-9][0-9])_(.+) ]]; then
85
+ echo "weight: ${BASH_REMATCH[1]}" >> _tmp
86
+ fi
87
+
88
+ # For _index.md files, add hideListLinks property
89
+ if [[ ${src} =~ _index.md$ ]]; then
90
+ echo "hideListLinks: true" >> _tmp
91
+ fi
92
+
93
+ # Close frontmatter
94
+ echo "---" >> _tmp
95
+ echo "" >> _tmp
96
+
97
+ # Write all of source file, except first line, in destination file
98
+ tail -n+2 ${src} >> _tmp
99
+
100
+ # _index.md files need title removed
101
+ if [[ ${src} =~ _index.md$ ]]; then
102
+ sed -i "s/# ${title}//" _tmp
103
+ fi
104
+
105
+ mv _tmp ${src}
106
+ }
107
+
108
+ # Convert jupyter notebooks to markdown
109
+ jupyter nbconvert --to markdown build/jupyter_execute/user_guide/*.ipynb --output-dir redis_vl_hugo/user_guide/ 2>/dev/null
110
+ jupyter nbconvert --to markdown build/jupyter_execute/overview/cli.ipynb --output-dir redis_vl_hugo/overview/ 2>/dev/null
111
+
112
+ # Prepare markdown files
113
+ rsync -a ./build/markdown/api/ ./redis_vl_hugo/api/ --exclude=index.md
114
+ cp ./build/markdown/overview/installation.md ./redis_vl_hugo/overview/installation.md
115
+
116
+ # Format markdown files
117
+ markdown_pages=(./redis_vl_hugo/**/*.md)
118
+
119
+ for markdown_page in "${markdown_pages[@]}"; do
120
+ format "${markdown_page}"
121
+
122
+ # Remove blockquotes and ansi stuff
123
+ sed -E -i 's/^> *//g; s/\x1b\[[0-9;]*m//g' "${markdown_page}"
124
+
125
+ # Replace https://docs.redisvl.com links
126
+ sed -E -i 's#https://docs.redisvl.com/en/latest/.+/([^_]+).+\.html(\#[^)]+)#{{< relref "\1\2" >}}#g; s#https://docs.redisvl.com/en/latest/(.+)\.html#https://redis.io/docs/latest/integrate/redisvl/\1#g' "${markdown_page}"
127
+ done
128
+
129
+ # Fix links in api pages
130
+ api_markdown_pages=(./redis_vl_hugo/api/*.md)
131
+
132
+ for api_markdown_page in "${api_markdown_pages[@]}"; do
133
+ gawk '
134
+ # handle relrefs to other pages
135
+ /\([A-Za-z]+\.md#redisvl\.[a-zA-Z0-9_.]+\)/ {
136
+ while (match($0, /\([A-Za-z]+\.md#redisvl\.[a-zA-Z0-9_.]+\)/)) {
137
+
138
+ m = substr($0, RSTART+1, RLENGTH-2)
139
+ split(m, parts, /[.#]/)
140
+ ref = "({{< relref \"" parts[1] "/#" tolower(parts[length(parts)]) "\" >}})"
141
+ $0 = substr($0, 1, RSTART-1) ref substr($0, RSTART+RLENGTH)
142
+
143
+ }
144
+ }
145
+ # handle relref same page
146
+ /\(#redisvl\.[^)]+\)/ {
147
+ while (match($0, /\[[^][]+\]\(#redisvl\.[^)]+\)/)) {
148
+
149
+ m = substr($0, RSTART+1, RLENGTH-2)
150
+ split(m, parts, /[.#]/)
151
+ ref = "[" parts[length(parts)] "]" "(" "#" tolower(parts[length(parts)]) ")"
152
+ $0 = substr($0, 1, RSTART-1) ref substr($0, RSTART+RLENGTH)
153
+ }
154
+ }
155
+ # format class/function signatures
156
+ /^####?/ {
157
+ # remove * from class, async, etc.
158
+ if ($2 ~ "^*") {
159
+ gsub(/\*/, "", $2)
160
+ }
161
+
162
+ # insert opening backtick
163
+ gsub(/^/,"`", $2)
164
+
165
+ if ($0 ~ /#### `.+: .*\[.+\]\(#.+\)/) {
166
+ # fix relrefs
167
+ gsub(/^/, "`", $4)
168
+ gsub(/`$/, "", $4)
169
+ gsub(/\*$/,"");
170
+ } else {
171
+ # insert closing backtick
172
+ $0 = $0 "`";
173
+ }
174
+ # unescape double asterisks, e.g. **kwargs
175
+ gsub(/\\\*\\\*/,"**");
176
+
177
+ # unespace underscores
178
+ gsub(/\\_/,"_");
179
+
180
+ # remove asterisks
181
+ gsub(/ ?\*:/,":");
182
+ gsub(/\*`$/,"`");
183
+
184
+ # handle ClassVar[ConfigDict]
185
+ gsub(/\* \*= \{/," = \{")
186
+
187
+ # handle *= in router.md
188
+ gsub(/ \*\= /, " = ");
189
+
190
+ # format rel links
191
+ if ($0 ~ /\[.+\]\(.+relref.+\)/) {
192
+ gsub(/\[/,"`[`")
193
+ gsub(/\]/,"`]")
194
+ gsub(/\)/,")` ")
195
+ }
196
+ # unescape single asterisks, e.g. *args
197
+ gsub(/\\\*/,"*");
198
+ }
199
+ {
200
+ # fix parameters
201
+ gsub(/\*\[\*\*/,"\*\[\* \*");
202
+ gsub(/\*\(\*\*/,"\*\(\* \*");
203
+ print $0
204
+ }
205
+ ' "${api_markdown_page}" > _tmp && mv _tmp "${api_markdown_page}"
206
+ done
207
+
208
+ # Format _index.md pages
209
+ cp ./build/markdown/api/index.md ./redis_vl_hugo/api/_index.md
210
+ cp ./build/markdown/user_guide/index.md ./redis_vl_hugo/user_guide/_index.md
211
+ cp ./build/markdown/overview/index.md ./redis_vl_hugo/overview/_index.md
212
+
213
+ index_markdown_pages=(
214
+ ./redis_vl_hugo/api/_index.md
215
+ ./redis_vl_hugo/user_guide/_index.md
216
+ ./redis_vl_hugo/overview/_index.md
217
+ )
218
+
219
+ for index_markdown_page in "${index_markdown_pages[@]}"; do
220
+ format "${index_markdown_page}"
221
+
222
+ # Fix relrefs by removing .md extension and references to numbered pages
223
+ sed -E -i 's/\.md/\//g; s/\([0-9]+_/\(/g' "${index_markdown_page}"
224
+ done
225
+
226
+ # Rename user guides to strip leading numbers from filename
227
+ user_guides=(./redis_vl_hugo/user_guide/*.md)
228
+ for user_guide in "${user_guides[@]}"; do
229
+ if [[ ! "$user_guide" =~ _index.md$ ]]; then
230
+ renamed_user_guide=$(sed 's|[0-9]\+_||' <<<${user_guide})
231
+ mv ${user_guide} ${renamed_user_guide}
232
+ fi
233
+ done
234
+
235
+ cp -r redis_vl_hugo/* content/integrate/redisvl/
236
+
237
+ - name : ' Create pull request if necessary'
238
+ env :
239
+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
240
+ run : |
241
+ release="${{ steps.sphinx.outputs.release }}"
242
+ branch="redisvl_docs_sync_${release}"
243
+ redisvl_change=false
244
+
245
+ # check if remote branch already exists
246
+ git fetch --all
247
+ set +e
248
+ git ls-remote --exit-code --heads origin "refs/heads/${branch}"
249
+ if [ "$?" -eq 0 ]; then
250
+ set -e
251
+ # if it does, create local branch off existing remote branch
252
+ git checkout -b "${branch}" "origin/${branch}"
253
+ git branch --set-upstream-to="origin/${branch}" "${branch}"
254
+ git pull
255
+ else
256
+ set -e
257
+ # otherwise, create local branch from main
258
+ git checkout -b "${branch}"
259
+ fi
260
+
261
+ redisvl_is_different=$(git diff content/integrate/redisvl/)
262
+
263
+ if [[ ! -z $redisvl_is_different ]]; then
264
+ redisvl_change=true
265
+
266
+ git add "content/integrate/redisvl/"
267
+ git config user.email "177626021+redisdocsapp[bot]@users.noreply.github.com"
268
+ git config user.name "redisdocsapp[bot]"
269
+ git commit -m "Update for redisvl ${release}"
270
+ fi
271
+
272
+ if [ "$redisvl_change" = true ] ; then
273
+ git push origin "${branch}"
274
+
275
+ # If a pr is not already open, create one
276
+ set +e
277
+ gh search prs -R redis/docs --state open --match title "update for redisvl ${release}" | grep -q "update for redisvl ${release}"
278
+ if [ "$?" -eq 1 ]; then
279
+ set -e
280
+ gh pr create \
281
+ --body "update for redisvl ${release}" \
282
+ --title "update for redisvl ${release}" \
283
+ --head "$branch" \
284
+ --base "main"
285
+ fi
286
+ fi
0 commit comments