1+ name : GitHub Pages PR Preview
2+
3+ on :
4+ pull_request :
5+ types : [opened, synchronize, reopened, closed]
6+ paths :
7+ - ' src/main/resources/templates/**'
8+ - ' src/main/resources/static/**'
9+ - ' src/main/resources/explanations/**'
10+ - ' src/main/java/**'
11+
12+ permissions :
13+ contents : read
14+ pages : write
15+ id-token : write
16+ pull-requests : write
17+
18+ # Allow only one concurrent deployment per PR, skipping runs queued between the run in-progress and latest queued.
19+ concurrency :
20+ group : " pages-pr-${{ github.event.number }}"
21+ cancel-in-progress : false
22+
23+ jobs :
24+ generate-static-preview :
25+ runs-on : ubuntu-latest
26+ if : github.event.action != 'closed'
27+ environment :
28+ name : github-pages
29+ url : ${{ steps.deployment.outputs.page_url }}pr-${{ github.event.number }}/
30+ outputs :
31+ preview-url : ${{ steps.deployment.outputs.page_url }}pr-${{ github.event.number }}/
32+ steps :
33+ - name : Checkout
34+ uses : actions/checkout@v4
35+
36+ - name : Set up JDK 23
37+ uses : actions/setup-java@v4
38+ with :
39+ java-version : " 23"
40+ distribution : " oracle"
41+ cache : " maven"
42+
43+ - name : Build application (JAR only)
44+ run : |
45+ echo "Building WrongSecrets application..."
46+ ./mvnw --no-transfer-progress clean package -DskipTests
47+
48+ # Verify JAR was created
49+ find target -name "*.jar" -type f | head -5
50+
51+ - name : Create static preview content
52+ run : |
53+ echo "Creating static preview for PR #${{ github.event.number }}..."
54+
55+ # Create the preview directory structure
56+ mkdir -p static-site/pr-${{ github.event.number }}
57+
58+ # Copy static assets (CSS, JS, images, etc.)
59+ echo "Copying static assets..."
60+ cp -r src/main/resources/static/* static-site/pr-${{ github.event.number }}/ 2>/dev/null || true
61+
62+ # Create a simple landing page for this PR preview
63+ cat > static-site/pr-${{ github.event.number }}/index.html << 'EOF'
64+ <!DOCTYPE html>
65+ <html lang="en">
66+ <head>
67+ <meta charset="UTF-8">
68+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
69+ <title>WrongSecrets PR Preview</title>
70+ <link href="css/bootstrap.min.css" rel="stylesheet" />
71+ <link href="css/custom.css" rel="stylesheet" />
72+ <link rel="icon" type="image/png" href="favicon.png">
73+ </head>
74+ <body>
75+ <div class="container-fluid mt-3">
76+ <div class="row">
77+ <div class="col-md-12">
78+ <div class="display-5 mb-3">🔐 OWASP WrongSecrets</div>
79+ <div class="alert alert-info" role="alert">
80+ <h5 class="alert-heading">📋 PR Preview #${{ github.event.number }}</h5>
81+ <p><strong>Static Preview Notice:</strong> This is a static preview of the UI changes in this pull request.</p>
82+ <p><strong>Commit:</strong> <code>${{ github.sha }}</code></p>
83+ <p><strong>For full functionality:</strong> Please use the Docker preview from the <a href="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" target="_blank">GitHub Actions build</a>.</p>
84+ </div>
85+
86+ <div class="card">
87+ <div class="card-header">
88+ <h5>📁 Available Preview Content</h5>
89+ </div>
90+ <div class="card-body">
91+ <p>This static preview includes:</p>
92+ <ul>
93+ <li>✅ All CSS stylesheets and themes</li>
94+ <li>✅ JavaScript files and interactions</li>
95+ <li>✅ Images, icons, and static assets</li>
96+ <li>⚠️ Template structure (limited dynamic content)</li>
97+ </ul>
98+
99+ <h6 class="mt-3">📋 Key Files Changed in This PR:</h6>
100+ <div id="changed-files">
101+ <em>Loading changed files...</em>
102+ </div>
103+
104+ <div class="mt-3">
105+ <a href="${{ github.server_url }}/${{ github.repository }}/pull/${{ github.event.number }}" class="btn btn-primary" target="_blank">
106+ View Full PR Details
107+ </a>
108+ <a href="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" class="btn btn-secondary" target="_blank">
109+ Docker Preview (Full Functionality)
110+ </a>
111+ </div>
112+ </div>
113+ </div>
114+ </div>
115+ </div>
116+ </div>
117+
118+ <script>
119+ // Try to fetch and display changed files information
120+ (async function() {
121+ try {
122+ const response = await fetch('${{ github.api_url }}/repos/${{ github.repository }}/pulls/${{ github.event.number }}/files');
123+ const files = await response.json();
124+
125+ const relevantFiles = files.filter(file =>
126+ file.filename.includes('templates/') ||
127+ file.filename.includes('static/') ||
128+ file.filename.includes('explanations/') ||
129+ file.filename.includes('src/main/java/')
130+ );
131+
132+ const changedFilesDiv = document.getElementById('changed-files');
133+ if (relevantFiles.length > 0) {
134+ changedFilesDiv.innerHTML = '<ul>' +
135+ relevantFiles.slice(0, 10).map(file =>
136+ `<li><code>${file.filename}</code> <span class="badge bg-${file.status === 'added' ? 'success' : file.status === 'removed' ? 'danger' : 'warning'}">${file.status}</span></li>`
137+ ).join('') +
138+ (relevantFiles.length > 10 ? `<li><em>... and ${relevantFiles.length - 10} more files</em></li>` : '') +
139+ '</ul>';
140+ } else {
141+ changedFilesDiv.innerHTML = '<em>No relevant UI/template files changed in this PR.</em>';
142+ }
143+ } catch (error) {
144+ console.log('Could not load changed files information:', error);
145+ document.getElementById('changed-files').innerHTML = '<em>Could not load changed files information.</em>';
146+ }
147+ })();
148+ </script>
149+ </body>
150+ </html>
151+ EOF
152+
153+ - name : Create preview directory index
154+ run : |
155+ # Create or update the main index page that lists all PR previews
156+ mkdir -p static-site
157+
158+ cat > static-site/index.html << 'EOF'
159+ <!DOCTYPE html>
160+ <html lang="en">
161+ <head>
162+ <meta charset="UTF-8">
163+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
164+ <title>OWASP WrongSecrets - PR Previews</title>
165+ <style>
166+ body {
167+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
168+ margin: 40px;
169+ background-color: #f8f9fa;
170+ }
171+ .container { max-width: 1200px; margin: 0 auto; }
172+ .header { text-align: center; margin-bottom: 40px; }
173+ .pr-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; }
174+ .pr-card {
175+ background: white;
176+ padding: 20px;
177+ border-radius: 8px;
178+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
179+ border-left: 4px solid #0366d6;
180+ }
181+ .pr-link { text-decoration: none; color: #0366d6; font-weight: bold; font-size: 1.2em; }
182+ .pr-link:hover { text-decoration: underline; }
183+ .meta { color: #666; font-size: 0.9em; margin-top: 10px; }
184+ .badge {
185+ background: #e1f5fe;
186+ color: #01579b;
187+ padding: 2px 8px;
188+ border-radius: 12px;
189+ font-size: 0.8em;
190+ }
191+ </style>
192+ </head>
193+ <body>
194+ <div class="container">
195+ <div class="header">
196+ <h1>🔐 OWASP WrongSecrets</h1>
197+ <h2>Pull Request Previews</h2>
198+ <p>Static previews of pull requests for UI and template changes</p>
199+ </div>
200+
201+ <div id="pr-list">
202+ <div class="pr-grid">
203+ <div class="pr-card">
204+ <a href="pr-${{ github.event.number }}/" class="pr-link">PR #${{ github.event.number }} Preview</a>
205+ <div class="meta">
206+ <span class="badge">Latest</span><br>
207+ Static preview of pull request #${{ github.event.number }}<br>
208+ Updated: <script>document.write(new Date().toLocaleString())</script>
209+ </div>
210+ </div>
211+ </div>
212+ </div>
213+
214+ <div style="text-align: center; margin-top: 40px; color: #666;">
215+ <p>
216+ <a href="${{ github.server_url }}/${{ github.repository }}" target="_blank">View Repository</a> |
217+ <a href="${{ github.server_url }}/${{ github.repository }}/pulls" target="_blank">All Pull Requests</a>
218+ </p>
219+ <small>Generated by GitHub Actions</small>
220+ </div>
221+ </div>
222+ </body>
223+ </html>
224+ EOF
225+
226+ - name : Setup Pages
227+ uses : actions/configure-pages@v5
228+
229+ - name : Upload artifact
230+ uses : actions/upload-pages-artifact@v3
231+ with :
232+ path : ./static-site
233+
234+ - name : Deploy to GitHub Pages
235+ id : deployment
236+ uses : actions/deploy-pages@v4
237+
238+ - name : Comment PR with preview link
239+ uses : actions/github-script@v7
240+ with :
241+ script : |
242+ const prNumber = context.issue.number;
243+ const previewUrl = `${{ steps.deployment.outputs.page_url }}pr-${prNumber}/`;
244+
245+ const comment = `🌐 **GitHub Pages Preview Ready!**
246+
247+ Your static preview is now available at:
248+ **🔗 [Preview PR #${prNumber}](${previewUrl})**
249+
250+ 📄 **What's included:**
251+ - ✅ All CSS, JavaScript, and static assets
252+ - ✅ Current styling and layout preview
253+ - ✅ Images, icons, and UI components
254+ - ⚠️ Limited dynamic functionality (static preview only)
255+
256+ **For full functionality testing:** Use the [Docker preview](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) instead.
257+
258+ **🔄 Auto-updates:** This preview will be updated automatically when you push new commits to this PR.
259+
260+ ---
261+ <sub>Static preview generated by GitHub Actions</sub>`;
262+
263+ github.rest.issues.createComment({
264+ issue_number: prNumber,
265+ owner: context.repo.owner,
266+ repo: context.repo.repo,
267+ body: comment
268+ });
269+
270+ cleanup-preview :
271+ runs-on : ubuntu-latest
272+ if : github.event.action == 'closed'
273+ steps :
274+ - name : Checkout gh-pages branch
275+ uses : actions/checkout@v4
276+ with :
277+ ref : gh-pages
278+ fetch-depth : 0
279+
280+ - name : Remove PR preview directory
281+ run : |
282+ PR_NUMBER=${{ github.event.number }}
283+ PR_DIR="pr-${PR_NUMBER}"
284+
285+ if [ -d "$PR_DIR" ]; then
286+ echo "Removing preview directory: $PR_DIR"
287+ rm -rf "$PR_DIR"
288+
289+ # Configure git
290+ git config user.name github-actions[bot]
291+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
292+
293+ # Commit and push the removal
294+ git add .
295+ git commit -m "Clean up preview for closed PR #${PR_NUMBER}" || echo "Nothing to commit"
296+ git push
297+ else
298+ echo "Preview directory $PR_DIR not found, nothing to clean up"
299+ fi
300+
301+ - name : Comment PR cleanup completion
302+ uses : actions/github-script@v7
303+ with :
304+ script : |
305+ const comment = `🧹 **Preview Cleanup Complete**
306+
307+ The static preview for this PR has been removed from GitHub Pages.
308+
309+ Thanks for contributing to WrongSecrets! 🎉
310+
311+ ---
312+ <sub>Cleanup completed by GitHub Actions</sub>`;
313+
314+ github.rest.issues.createComment({
315+ issue_number: context.issue.number,
316+ owner: context.repo.owner,
317+ repo: context.repo.repo,
318+ body: comment
319+ });
0 commit comments