Skip to content

Commit 9c06036

Browse files
authored
Merge pull request #133 from gperdrizet/dev
New pull request preview workflow
2 parents a375e19 + 1d2c5c6 commit 9c06036

14 files changed

+308
-125
lines changed

.github/workflows/test-gh-pages.yml

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,20 @@ name: Pages test
44
# Runs on pull request creation
55
on:
66
pull_request:
7-
types: [opened, reopened]
7+
types: [opened, reopened, synchronize]
88

99
# Allows you to run this workflow manually from the Actions tab
1010
workflow_dispatch:
1111

12-
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
12+
# Sets permissions of the GITHUB_TOKEN
1313
permissions:
1414
contents: read
15-
pages: write
16-
id-token: write
15+
pull-requests: write
1716

18-
# Allow only one concurrent build, skipping runs queued between the run in-progress and latest queued.
17+
# Allow only one concurrent build per PR
1918
concurrency:
20-
group: "build-pages"
21-
cancel-in-progress: false
19+
group: "build-pages-pr-${{ github.event.pull_request.number || github.run_id }}"
20+
cancel-in-progress: true
2221

2322
jobs:
2423
# Build job
@@ -28,49 +27,35 @@ jobs:
2827
steps:
2928
- name: Checkout
3029
uses: actions/checkout@v4
31-
- name: Setup Pages
32-
uses: actions/configure-pages@v5
33-
34-
- name: Create _site directory
35-
run: mkdir -p ./site/_site
36-
37-
- name: Create notebooks directory
38-
run: mkdir -p ./site/assets/notebooks
39-
- name: Move notebooks into build directory
40-
run: cp -r ./notebooks/* ./site/assets/notebooks/
41-
- name: Move notebook config file into build directory
42-
run: cp -r ./notebooks/notebooks.yml ./site/_data/
43-
44-
- name: Create data directory
45-
run: mkdir -p ./site/assets/data
46-
- name: Move datasets into build directory
47-
run: cp -r ./data/* ./site/assets/data/
48-
- name: Move dataset config file into build directory
49-
run: cp -r ./data/datasets.yml ./site/_data/
50-
51-
- name: Move resources page into build directory
52-
run: cp ./resources.md ./site/
53-
54-
- name: Build with Jekyll
55-
uses: actions/jekyll-build-pages@v1
30+
31+
- name: Setup Ruby
32+
uses: ruby/setup-ruby@v1
5633
with:
57-
source: ./site
58-
destination: ./site/_site
59-
- name: Upload artifact
60-
uses: actions/upload-pages-artifact@v3
34+
ruby-version: '3.1'
35+
bundler-cache: false
36+
37+
- name: Install dependencies
38+
run: make install
39+
40+
- name: Build site with Makefile
41+
run: make build-github
42+
43+
- name: Comment on PR
44+
if: github.event_name == 'pull_request'
45+
uses: actions/github-script@v7
6146
with:
62-
path: ./site/_site
63-
64-
# Deployment job
65-
deploy:
66-
name: Test deploy pages site
67-
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
68-
environment:
69-
name: github-pages-test
70-
url: ${{ steps.deployment.outputs.page_url }}
71-
runs-on: ubuntu-latest
72-
needs: build
73-
steps:
74-
- name: Deploy to GitHub Pages
75-
id: deployment
76-
uses: actions/deploy-pages@v4
47+
script: |
48+
const prNumber = context.issue.number;
49+
const message = `**Build successful!**
50+
51+
Your preview deployment will be available on Render at:
52+
https://fsa-devops-preview-pr-${prNumber}.onrender.com
53+
54+
Note: Render preview deployments may take a few minutes to become available after the build completes.`;
55+
56+
github.rest.issues.createComment({
57+
issue_number: prNumber,
58+
owner: context.repo.owner,
59+
repo: context.repo.repo,
60+
body: message
61+
});

Makefile

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Makefile for FSA_devops Jekyll site build automation
2+
# This file provides targets for building, testing, and deploying the Jekyll site
3+
4+
.PHONY: help install clean copy-notebooks copy-data copy-resources copy-all build-github build-render serve-local validate-links
5+
6+
# Default target - show help
7+
help:
8+
@echo "Available targets:"
9+
@echo " install - Install Ruby dependencies via bundle install"
10+
@echo " clean - Remove built site and copied assets"
11+
@echo " copy-notebooks - Copy notebook files to site/assets/notebooks"
12+
@echo " copy-data - Copy data files to site/assets/data"
13+
@echo " copy-resources - Copy resources.md to site directory"
14+
@echo " copy-all - Run all copy targets"
15+
@echo " build-github - Build site for GitHub Pages (with baseurl)"
16+
@echo " build-render - Build site for Render.com (without baseurl)"
17+
@echo " serve-local - Serve site locally (matches GitHub Pages config)"
18+
@echo " validate-links - Check for broken internal links using linkchecker"
19+
20+
# Install dependencies
21+
install:
22+
@echo "Installing Ruby dependencies..."
23+
cd site && bundle install
24+
25+
# Clean built site and copied assets
26+
clean:
27+
@echo "Cleaning built site and copied assets..."
28+
rm -rf site/_site
29+
rm -rf site/assets/notebooks
30+
rm -rf site/assets/data
31+
rm -f site/resources.md
32+
33+
# Copy notebooks to site assets
34+
copy-notebooks:
35+
@echo "Copying notebooks to site/assets/notebooks..."
36+
mkdir -p site/assets/notebooks
37+
cp -r notebooks/* site/assets/notebooks/
38+
mkdir -p site/_data
39+
cp notebooks/notebooks.yml site/_data/
40+
41+
# Copy data files to site assets
42+
copy-data:
43+
@echo "Copying data files to site/assets/data..."
44+
mkdir -p site/assets/data
45+
cp -r data/* site/assets/data/
46+
mkdir -p site/_data
47+
cp data/datasets.yml site/_data/
48+
49+
# Copy resources.md to site directory
50+
copy-resources:
51+
@echo "Copying resources.md to site..."
52+
cp resources.md site/
53+
54+
# Copy all assets
55+
copy-all: copy-notebooks copy-data copy-resources
56+
@echo "All assets copied successfully"
57+
58+
# Build for GitHub Pages (with baseurl)
59+
build-github: copy-all
60+
@echo "Building site for GitHub Pages..."
61+
cd site && bundle exec jekyll build
62+
63+
# Build for Render.com (merged config without baseurl)
64+
build-render: copy-all
65+
@echo "Building site for Render.com..."
66+
cd site && bundle exec jekyll build --config _config.yml,_config_render.yml
67+
68+
# Serve site locally (matches GitHub Pages production config)
69+
serve-local: copy-all
70+
@echo "Starting local Jekyll server..."
71+
cd site && bundle exec jekyll serve --livereload
72+
73+
# Validate links (internal only, no external link checking)
74+
validate-links:
75+
@echo "Validating internal links..."
76+
@if ! command -v linkchecker &> /dev/null; then \
77+
echo "Error: linkchecker not found. Install with: pip install linkchecker"; \
78+
exit 1; \
79+
fi
80+
linkchecker --check-extern=no site/_site

README.md

Lines changed: 101 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,43 @@ This approach reduces maintenance burden by significantly. Adding new content re
6060

6161
**Custom Components**: The `_includes/header.html` file implements navigation filtering to exclude pages with `nav_exclude: true` in their front matter, enabling draft pages and hidden content.
6262

63-
## 2. CI/CD Pipeline
63+
## 3. CI/CD Pipeline
6464

65-
The main branch has protections in place that prevent direct pushes without a pull request. To merge a pull request into main, a test deployment must first be made successfully.
65+
The main branch has protections in place that prevent direct pushes without a pull request. To merge a pull request into main, a test build and preview deployment must first complete successfully.
6666

67-
### 1. Pull Request Preview (`test-gh-pages.yml`)
67+
### 3.1. Pull Request Preview Workflow
6868

69-
- **Trigger**: PR creation/reopening or manual dispatch
70-
- **Purpose**: Validates that site builds successfully before merging to `main`
71-
- **Process**: Identical build steps to production workflow but deploys to `github-pages-test` environment
69+
When you open a PR from `dev` to `main`, two automated processes run:
7270

73-
### 2. Production Deployment (`deploy-gh-pages.yml`)
71+
#### GitHub Actions Build (`test-gh-pages.yml`)
72+
- **Trigger**: PR opened/reopened/synchronized or manual dispatch
73+
- **Purpose**: Validates that site builds successfully with the Makefile-based workflow
74+
- **Process**:
75+
1. Checks out repository code
76+
2. Sets up Ruby environment
77+
3. Runs `make build-github` to build site with production config
78+
4. Posts comment on PR with Render preview URL
79+
- **Output**: Build status check on PR
80+
81+
#### Render.com Preview Deployment
82+
- **Trigger**: PR opened from `dev` branch (automatic via Render PR preview feature)
83+
- **Purpose**: Creates a live preview of changes before merging to production
84+
- **Process**:
85+
1. Installs Ruby dependencies: `cd site && bundle install`
86+
2. Builds site with Render config: `make build-render` (uses merged `_config.yml` + `_config_render.yml`)
87+
3. Deploys to temporary preview URL: `fsa-devops-preview-pr-{NUMBER}.onrender.com`
88+
- **URL Format**: Each PR gets a unique preview URL (e.g., `fsa-devops-preview-pr-42.onrender.com`)
89+
- **Lifecycle**: Preview deployment is automatically deleted when PR is closed/merged
90+
- **Config Files**:
91+
- `site/_config.yml`: Production config with `baseurl: "/FSA_devops"`
92+
- `site/_config_render.yml`: Override config with empty baseurl for root-level deployment
93+
94+
**Why Two Configs?**
95+
- GitHub Pages deploys to a subpath: `gperdrizet.github.io/FSA_devops/`
96+
- Render deploys to root: `fsa-devops-preview-pr-42.onrender.com/`
97+
- Jekyll's `relative_url` filter uses `baseurl` to generate correct URLs for each environment
98+
99+
### 3.2. Production Deployment (`deploy-gh-pages.yml`)
74100

75101
- **Trigger**: Pushes to `main` branch or manual dispatch
76102
- **Process**:
@@ -89,42 +115,102 @@ The main branch has protections in place that prevent direct pushes without a pu
89115
- Validates YAML syntax and Liquid template logic
90116
- Ensures asset copying and file structure integrity
91117
- Provides build status checks on PRs via badges
118+
- Enables visual review of changes before production deployment
119+
- Supports collaborative review with live preview links
120+
121+
## 4. Build System
122+
123+
The repository uses a Makefile-based build system for consistent asset management and Jekyll compilation across environments.
124+
125+
### Available Make Targets
126+
127+
```bash
128+
make help # Show all available targets
129+
make install # Install Ruby dependencies (bundle install)
130+
make clean # Remove built site and copied assets
131+
make copy-notebooks # Copy notebooks to site/assets/notebooks
132+
make copy-data # Copy datasets to site/assets/data
133+
make copy-resources # Copy resources.md to site/
134+
make copy-all # Run all copy targets
135+
make build-github # Build for GitHub Pages (with baseurl)
136+
make build-render # Build for Render.com (without baseurl)
137+
make serve-local # Start local Jekyll server
138+
make validate-links # Check for broken internal links
139+
```
140+
141+
### Multi-Environment Support
92142

93-
## 3. Development Workflow
143+
The build system supports two deployment targets:
144+
145+
**GitHub Pages** (`make build-github`):
146+
- Uses `site/_config.yml` only
147+
- Sets `baseurl: "/FSA_devops"` for subpath deployment
148+
- URLs generated as: `/FSA_devops/path/to/resource`
149+
150+
**Render.com** (`make build-render`):
151+
- Merges `site/_config.yml` + `site/_config_render.yml`
152+
- Overrides baseurl to empty string for root deployment
153+
- URLs generated as: `/path/to/resource`
154+
155+
All internal URLs use Jekyll's `relative_url` filter, which automatically adjusts based on the `baseurl` setting.
156+
157+
## 5. Development Workflow
158+
159+
## 5. Development Workflow
94160

95161
### Branch Strategy
96162

97163
- **`main`**: Production branch - triggers automatic deployment to GitHub Pages
98164
- **`dev`**: Development branch - used for feature work and testing
99165
- **Feature branches**: Created as needed for specific enhancements
100166

167+
### Pull Request Process
168+
169+
1. **Create PR**: Open pull request from `dev` to `main` on GitHub
170+
2. **Automated Checks**:
171+
- GitHub Actions builds site and reports status
172+
- Render creates preview deployment (link posted in PR comment)
173+
3. **Review Changes**: Visit preview URL to verify changes work correctly
174+
4. **Merge**: Once approved and checks pass, merge to `main`
175+
5. **Deploy**: Production deployment to GitHub Pages triggers automatically
176+
6. **Cleanup**: Render automatically deletes preview deployment
177+
101178
### Local Development
102179

103180
The repository includes a dev container configuration for consistent development environments.
104181

105-
Jekyll's incremental build feature enables rapid iteration - most changes appear on local development server within seconds of saving files:
182+
Jekyll's live reload enables rapid iteration - most changes appear in your browser within seconds:
106183

107184
```bash
108-
# Start local Jekyll server
109-
cd site && bundle exec jekyll serve
185+
# Start local Jekyll server (matches GitHub Pages config)
186+
make serve-local
110187

111-
# Site available at http://localhost:4000
188+
# Site available at http://localhost:4000/FSA_devops
189+
# Automatically rebuilds on file changes
112190
```
113191

192+
**Note**: Local server uses production config with baseurl, so URLs will include `/FSA_devops` prefix.
193+
114194
### Content Updates
115195

116196
**Adding Notebooks**:
117197
1. Place `.ipynb` file in appropriate `notebooks/unit*/lesson*/` directory
118198
2. Add metadata entry to `notebooks/notebooks.yml`
119-
3. Commit and push - workflow automatically copies to build directory
199+
3. Commit and push - build process automatically copies to site assets
120200

121201
**Adding Datasets**:
122202
1. Place CSV file in `data/` directory
123203
2. Add metadata to `data/datasets.yml`
124-
3. Workflow handles asset copying during build
204+
3. Build process handles asset copying during deployment
125205

126206
**Writing Blog Posts**:
127207
1. Create markdown file in `site/_posts/` using naming convention: `YYYY-MM-DD-title.md`
128208
2. Include YAML front matter with `layout`, `title`, `date`, and optional `categories`
129-
3. Jekyll automatically includes posts in chronological order on homepage
209+
3. Use `{{ '/path/to/resource' | relative_url }}` for any internal links
210+
4. Jekyll automatically includes posts in chronological order on homepage
211+
212+
**Updating Resources**:
213+
1. Edit `resources.md` in repository root
214+
2. Use `{{ '/path' | relative_url }}` filter for all internal links
215+
3. Build process copies file to `site/` directory
130216

render.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Render.com Blueprint for FSA_devops Preview Deployments
2+
# This file defines the infrastructure for automatic PR preview deployments
3+
4+
services:
5+
- type: web
6+
name: fsa-devops-preview
7+
env: static
8+
branch: dev
9+
buildCommand: cd site && bundle install && cd .. && make build-render
10+
staticPublishPath: ./site/_site
11+
pullRequestPreviewsEnabled: true
12+
headers:
13+
- path: /*
14+
name: Cache-Control
15+
value: public, max-age=3600
16+
routes:
17+
- type: rewrite
18+
source: /*
19+
destination: /index.html

0 commit comments

Comments
 (0)