docs: add MLflow integration guide #251
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Docs Check | |
| on: | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - 'docs/**' | |
| - 'website/**' | |
| jobs: | |
| validate-docs: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: website | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v1 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Check for relative links without .md extension | |
| working-directory: . | |
| run: | | |
| # Relative doc links without .md are passed through as raw href values. | |
| # GitHub Pages adds trailing slashes, which breaks browser resolution of | |
| # relative paths. Links with .md are resolved by Docusaurus at build time. | |
| SKIP_MD_EXTENSIONS='\.md[)#]' | |
| SKIP_IMAGE_EXTENSIONS='\.(png|jpg|svg|gif)\)' | |
| SKIP_CODE_EXTENSIONS='\.go\)' | |
| SKIP_REMOTE_LINKS='http' | |
| # Search for relative links, then drop (grep -v) the ones that match our skip patterns | |
| matches=$(grep -rEn '\]\(\.\.?/' docs/ --include='*.md' | \ | |
| grep -vE "$SKIP_MD_EXTENSIONS" | \ | |
| grep -vE "$SKIP_IMAGE_EXTENSIONS" | \ | |
| grep -vE "$SKIP_CODE_EXTENSIONS" | \ | |
| grep -vE "$SKIP_REMOTE_LINKS" \ | |
| || true) | |
| if [ -n "$matches" ]; then | |
| while IFS=: read -r file line content; do | |
| echo "::error file=${file},line=${line}::Relative link without .md extension will break on GitHub Pages. Use ./foo.md instead of ./foo" | |
| done <<< "$matches" | |
| exit 1 | |
| fi | |
| - name: Build | |
| id: build | |
| continue-on-error: true | |
| env: | |
| CI_LINT: 'true' | |
| NO_COLOR: '1' | |
| run: | | |
| set -o pipefail | |
| bun run build 2>&1 | tee /tmp/build-output.txt | |
| - name: Annotate broken links | |
| id: annotate | |
| working-directory: . | |
| run: | | |
| current_file="" | |
| found_broken=false | |
| declare -A seen_annotations | |
| # Regex stored in variable to avoid bash [[ =~ ]] quoting issues | |
| mdx_re='Markdown link with URL .([^ ]+). in source file "\.\./([^"]+)" \(([0-9]+):' | |
| emit_annotation() { | |
| local file="$1" line="$2" link="$3" | |
| local key="${file}:${line}:${link}" | |
| if [[ -z "${seen_annotations[$key]+x}" ]]; then | |
| seen_annotations[$key]=1 | |
| if [[ -n "$line" ]]; then | |
| echo "::error file=${file},line=${line}::Broken link: '${link}' could not be resolved" | |
| else | |
| echo "::error file=${file}::Broken link: '${link}' could not be resolved" | |
| fi | |
| found_broken=true | |
| fi | |
| } | |
| while IFS= read -r line; do | |
| # Format 1: MDX compilation errors (markdown links caught during build) | |
| # e.g. Markdown link with URL `testing.md` in source file "../docs/contributing/index.md" (63:21) couldn't be resolved. | |
| if [[ "$line" =~ $mdx_re ]]; then | |
| broken_link="${BASH_REMATCH[1]}" | |
| source_file="${BASH_REMATCH[2]}" | |
| line_num="${BASH_REMATCH[3]}" | |
| emit_annotation "$source_file" "$line_num" "$broken_link" | |
| fi | |
| # Format 2: Post-build broken route links | |
| # e.g. - Broken link on source page path = /michelangelo/docs/guides/api: | |
| # -> linking to /michelangelo/docs/nonexistent | |
| if [[ "$line" =~ "Broken link on source page path = /michelangelo/"(.*): ]]; then | |
| page_path="${BASH_REMATCH[1]}" | |
| page_path="${page_path%/}" | |
| if [[ -f "${page_path}/index.md" ]]; then | |
| current_file="${page_path}/index.md" | |
| elif [[ -f "${page_path}.md" ]]; then | |
| current_file="${page_path}.md" | |
| else | |
| current_file="" | |
| fi | |
| fi | |
| if [[ "$line" =~ "-> linking to "([^[:space:]]+) ]]; then | |
| broken_link="${BASH_REMATCH[1]}" | |
| # Strip baseUrl prefix so grep matches source text | |
| search_link="${broken_link#/michelangelo}" | |
| if [[ -n "$current_file" ]]; then | |
| line_nums=$(grep -n "$search_link" "$current_file" 2>/dev/null | cut -d: -f1) | |
| if [[ -n "$line_nums" ]]; then | |
| while IFS= read -r line_num; do | |
| emit_annotation "$current_file" "$line_num" "$search_link" | |
| done <<< "$line_nums" | |
| else | |
| emit_annotation "$current_file" "" "$search_link" | |
| fi | |
| else | |
| # Source file couldn't be resolved (e.g. custom slug), search all docs | |
| matches=$(grep -rn "$search_link" docs/ --include='*.md' 2>/dev/null | head -5) | |
| if [[ -n "$matches" ]]; then | |
| while IFS=: read -r file line_num _; do | |
| emit_annotation "$file" "$line_num" "$search_link" | |
| done <<< "$matches" | |
| fi | |
| fi | |
| fi | |
| done < /tmp/build-output.txt | |
| if [[ "$found_broken" == "true" ]]; then | |
| echo "found=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Fail if broken links or build error | |
| if: steps.build.outcome == 'failure' || steps.annotate.outputs.found == 'true' | |
| run: | | |
| if [[ "${{ steps.annotate.outputs.found }}" == "true" ]] && [[ "${{ steps.build.outcome }}" == "failure" ]]; then | |
| echo "Build failed and broken links were found. See annotations above for details." | |
| elif [[ "${{ steps.annotate.outputs.found }}" == "true" ]]; then | |
| echo "Broken links were found. See annotations above for details." | |
| else | |
| echo "Build failed. Check the build step logs for details." | |
| fi | |
| exit 1 |