|
6 | 6 | * - Template placeholders are replaced |
7 | 7 | * - Version sections exist |
8 | 8 | * - Links are properly formatted |
9 | | - * - External links are accessible |
| 9 | + * - Relative documentation links point to existing files |
| 10 | + * |
| 11 | + * Environment Variables: |
| 12 | + * - VERIFY_DOCS_BASE_URL: Base URL for documentation files (default: https://docs.nextcloud.com) |
| 13 | + * Set to empty string to skip file existence checks |
10 | 14 | */ |
11 | 15 |
|
12 | 16 | $html_file = 'build/index.html'; |
| 17 | +$base_url = getenv('VERIFY_DOCS_BASE_URL') ?: 'https://docs.nextcloud.com'; |
13 | 18 |
|
14 | 19 | if (!file_exists($html_file)) { |
15 | 20 | fwrite(STDERR, "⚠️ $html_file not found\n"); |
|
50 | 55 | $version_count = preg_match_all('/<h2>Nextcloud (\d+)/', $content, $versions); |
51 | 56 | fprintf(STDERR, "✓ Found %d version sections: %s\n", $version_count, implode(', ', $versions[1])); |
52 | 57 |
|
53 | | -// Validate documentation links format (should be /server/VERSION/) |
54 | | -$docs_links = array_filter($external_links, fn($l) => preg_match('~docs\.[^/]+/server/~', $l)); |
| 58 | +// Validate documentation links format (should be server/VERSION/) |
| 59 | +// Check both relative links (server/latest, server/stable, etc.) and external docs links |
| 60 | +$relative_docs_links = array_filter($relative_links, fn($l) => preg_match('~^server/(latest|stable|\d+)/~', $l)); |
| 61 | +$external_docs_links = array_filter($external_links, fn($l) => preg_match('~docs\.[^/]+/server/~', $l)); |
| 62 | +$all_docs_links = array_merge($relative_docs_links, $external_docs_links); |
55 | 63 |
|
56 | | -if (!empty($docs_links)) { |
57 | | - $invalid_docs = array_filter($docs_links, fn($l) => |
58 | | - !preg_match('~/server/(latest|stable|\d+)/~', $l) |
| 64 | +if (!empty($all_docs_links)) { |
| 65 | + $invalid_docs = array_filter($all_docs_links, fn($l) => |
| 66 | + !preg_match('~(server|/server)/(latest|stable|\d+)/~', $l) |
59 | 67 | ); |
60 | 68 |
|
61 | 69 | if (!empty($invalid_docs)) { |
|
64 | 72 | fprintf(STDERR, " - %s\n", $link); |
65 | 73 | } |
66 | 74 | } else { |
67 | | - fprintf(STDERR, "✓ All %d documentation links are properly formatted\n", count($docs_links)); |
| 75 | + fprintf(STDERR, "✓ All %d documentation links are properly formatted\n", count($all_docs_links)); |
68 | 76 | } |
69 | 77 | } |
70 | 78 |
|
|
106 | 114 | exit(1); |
107 | 115 | } |
108 | 116 |
|
| 117 | +// Test documentation file existence on deployed site (if base URL is configured) |
| 118 | +if ($base_url) { |
| 119 | + fprintf(STDERR, "\nVerifying documentation files on %s...\n", $base_url); |
| 120 | + |
| 121 | + $relative_docs = array_filter($relative_links, fn($l) => preg_match('~^server/(latest|stable|\d+)/~', $l)); |
| 122 | + |
| 123 | + if (!empty($relative_docs)) { |
| 124 | + $missing_files = []; |
| 125 | + $timeout_files = []; |
| 126 | + |
| 127 | + foreach ($relative_docs as $relative_path) { |
| 128 | + $full_url = rtrim($base_url, '/') . '/' . $relative_path; |
| 129 | + |
| 130 | + $context = stream_context_create([ |
| 131 | + 'http' => [ |
| 132 | + 'method' => 'HEAD', |
| 133 | + 'timeout' => 5, |
| 134 | + 'ignore_errors' => true, |
| 135 | + 'user_agent' => 'Mozilla/5.0' |
| 136 | + ] |
| 137 | + ]); |
| 138 | + |
| 139 | + $response = @get_headers($full_url, true, $context); |
| 140 | + |
| 141 | + if ($response === false) { |
| 142 | + $timeout_files[] = $relative_path; |
| 143 | + fprintf(STDERR, " ⚠️ %s - timeout/offline\n", $relative_path); |
| 144 | + } else { |
| 145 | + $status_line = $response[0] ?? ''; |
| 146 | + if (preg_match('/\d{3}/', $status_line, $match)) { |
| 147 | + $status = (int)$match[0]; |
| 148 | + if ($status === 404) { |
| 149 | + $missing_files[] = $relative_path; |
| 150 | + fprintf(STDERR, " ✗ %s - 404 Not Found\n", $relative_path); |
| 151 | + } else if ($status >= 400) { |
| 152 | + fprintf(STDERR, " ⚠️ %s - HTTP %d\n", $relative_path, $status); |
| 153 | + } else if ($status === 200 || $status === 301 || $status === 302) { |
| 154 | + fprintf(STDERR, " ✓ %s\n", $relative_path); |
| 155 | + } |
| 156 | + } |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + if (!empty($missing_files)) { |
| 161 | + fprintf(STDERR, "\n❌ ERROR: %d documentation files not found:\n", count($missing_files)); |
| 162 | + foreach ($missing_files as $file) { |
| 163 | + fprintf(STDERR, " - %s\n", $file); |
| 164 | + } |
| 165 | + exit(1); |
| 166 | + } |
| 167 | + |
| 168 | + if (count($timeout_files) >= count($relative_docs) / 2) { |
| 169 | + fprintf(STDERR, "\n⚠️ WARNING: %d/%d files timed out (site may be offline)\n", count($timeout_files), count($relative_docs)); |
| 170 | + } |
| 171 | + } |
| 172 | +} |
| 173 | + |
109 | 174 | fprintf(STDERR, "\n✓ index.html validation passed\n"); |
110 | 175 | exit(0); |
0 commit comments