Skip to content

Commit 06e8d0b

Browse files
authored
Merge pull request #10 from rust-stuco/feat/auto-update-homework-workflow
Automatically generate HW from homeworks repository
2 parents 98a877f + 3fdc8ed commit 06e8d0b

File tree

11 files changed

+1231
-4106
lines changed

11 files changed

+1231
-4106
lines changed

.eleventy.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
const eleventyNavigationPlugin = require("@11ty/eleventy-navigation");
1+
const EleventyNavigationPlugin = require("@11ty/eleventy-navigation");
2+
const { EleventyHtmlBasePlugin } = require("@11ty/eleventy");
23

3-
const dateFilterPlugin = require('nunjucks-date-filter');
4-
5-
const markdownIt = require('markdown-it')
6-
const markdownItAttrs = require('markdown-it-attrs')
4+
const markdownIt = require("markdown-it")
5+
const markdownItAttrs = require("markdown-it-attrs")
76

87
const markdownItOptions = {
98
html: true,
@@ -13,10 +12,10 @@ const markdownItOptions = {
1312

1413
const markdownLib = markdownIt(markdownItOptions).use(markdownItAttrs)
1514

16-
1715
module.exports = function(eleventyConfig) {
18-
eleventyConfig.setLibrary('md', markdownLib)
19-
eleventyConfig.addPlugin(eleventyNavigationPlugin);
16+
eleventyConfig.setLibrary("md", markdownLib)
17+
eleventyConfig.addPlugin(EleventyNavigationPlugin);
18+
eleventyConfig.addPlugin(EleventyHtmlBasePlugin);
2019

2120
// Copy assets
2221
eleventyConfig.addPassthroughCopy("assets/img/**/*")
@@ -37,4 +36,8 @@ module.exports = function(eleventyConfig) {
3736
eleventyConfig.addFilter("toISO", (dateObj) => {
3837
return dateObj.toISOString().substring(0, 10);
3938
});
39+
40+
return {
41+
pathPrefix: process.env.ELEVENTY_PATH_PREFIX || ""
42+
}
4043
};

.github/scripts/build-lab.sh

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#!/bin/bash
2+
3+
# Builds documentation and zip file for a lab
4+
5+
set -e
6+
7+
# Check arguments
8+
if [ $# -ne 2 ]; then
9+
echo "Usage: $0 <week_dir> <lab_name>"
10+
echo "Example: $0 week1 primerlab"
11+
exit 1
12+
fi
13+
14+
WEEK_DIR="$1"
15+
LAB_NAME="$2"
16+
HOMEWORKS_DIR="$(pwd)/homeworks-temp"
17+
LAB_PATH="$HOMEWORKS_DIR/$WEEK_DIR/$LAB_NAME"
18+
HW_OUTPUT_DIR="$(pwd)/hw"
19+
OUTPUT_DIR="$HW_OUTPUT_DIR/$LAB_NAME"
20+
21+
# Validate lab directory exists
22+
if [ ! -d "$LAB_PATH" ]; then
23+
echo "Error: Lab directory $LAB_PATH does not exist"
24+
exit 1
25+
fi
26+
27+
if [ ! -f "$LAB_PATH/Cargo.toml" ]; then
28+
echo "Error: No Cargo.toml found in $LAB_PATH"
29+
exit 1
30+
fi
31+
32+
echo "Building $LAB_NAME from $WEEK_DIR..."
33+
34+
mkdir -p "$OUTPUT_DIR"
35+
36+
cd "$LAB_PATH"
37+
38+
# Generate documentation
39+
echo " Generating documentation for $LAB_NAME..."
40+
if cargo doc --document-private-items; then
41+
if [ -d "target/doc" ]; then
42+
doc_dir="$OUTPUT_DIR/doc"
43+
mkdir -p "$doc_dir"
44+
cp -r target/doc/. "$doc_dir/"
45+
46+
echo " Documentation generated successfully for $LAB_NAME"
47+
else
48+
echo " Warning: No documentation generated for $LAB_NAME"
49+
fi
50+
else
51+
echo " Error: Failed to generate documentation for $LAB_NAME"
52+
exit 1
53+
fi
54+
55+
# Create zip file excluding target directory and Cargo.lock
56+
echo " Creating zip file for $LAB_NAME..."
57+
zip -r "$OUTPUT_DIR/$LAB_NAME.zip" . -x "target/*" "*.zip" "Cargo.lock"
58+
59+
echo "Successfully built $LAB_NAME"

.github/scripts/discover-labs.sh

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/bin/bash
2+
3+
# Discovers all labs in the homeworks repository
4+
5+
set -e
6+
7+
HOMEWORKS_DIR="$(pwd)/homeworks-temp"
8+
9+
if [ ! -d "$HOMEWORKS_DIR" ]; then
10+
echo "Error: Homeworks directory $HOMEWORKS_DIR does not exist"
11+
exit 1
12+
fi
13+
14+
cd "$HOMEWORKS_DIR"
15+
16+
labs=()
17+
for week_dir in week*/; do
18+
if [ ! -d "$week_dir" ]; then
19+
continue
20+
fi
21+
22+
# Look for lab directories
23+
for lab_dir in "$week_dir"*/; do
24+
if [ ! -d "$lab_dir" ]; then
25+
continue
26+
fi
27+
28+
lab_name=$(basename "$lab_dir")
29+
30+
# Skip reference implementations and autograder directories
31+
if [[ "$lab_name" == *"_ref" ]] || [[ "$lab_name" == "autograder" ]]; then
32+
continue
33+
fi
34+
35+
# Only process directories that end with "lab" and have Cargo.toml
36+
if [[ "$lab_name" == *"lab" ]] && [ -f "$lab_dir/Cargo.toml" ]; then
37+
week_name=$(basename "$week_dir")
38+
labs+=("{\"week\":\"$week_name\",\"lab\":\"$lab_name\"}")
39+
fi
40+
done
41+
done
42+
43+
# Output as JSON array for GitHub Actions matrix
44+
json_output="["
45+
for i in "${!labs[@]}"; do
46+
json_output+="${labs[$i]}"
47+
if [ $i -lt $((${#labs[@]} - 1)) ]; then
48+
json_output+=","
49+
fi
50+
done
51+
json_output+="]"
52+
53+
echo "$json_output"

.github/workflows/main.yml

Lines changed: 174 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,185 @@
1-
# On every push this script is executed
21
on:
32
push:
43
workflow_dispatch:
4+
repository_dispatch:
5+
types: [homework-update]
6+
57
name: Build and deploy GH Pages
8+
69
jobs:
7-
build:
10+
discover-labs:
811
runs-on: ubuntu-latest
12+
outputs:
13+
matrix: ${{ steps.set-matrix.outputs.matrix }}
14+
homeworks-hash: ${{ steps.homeworks-hash.outputs.hash }}
915
steps:
1016
- name: checkout
11-
uses: actions/checkout@v3
17+
uses: actions/checkout@v5
18+
19+
- name: Get homeworks repository commit hash
20+
id: homeworks-hash
21+
run: |
22+
HOMEWORKS_HASH=$(git ls-remote https://github.com/rust-stuco/homeworks.git HEAD | cut -f1)
23+
echo "hash=$HOMEWORKS_HASH" >> $GITHUB_OUTPUT
24+
25+
- name: Cache complete homework build
26+
id: cache-homework-build
27+
uses: actions/cache@v4
28+
with:
29+
path: hw
30+
key: homework-complete-${{ steps.homeworks-hash.outputs.hash }}
31+
32+
- name: Clone homeworks repository
33+
if: steps.cache-homework-build.outputs.cache-hit != 'true'
34+
run: |
35+
git clone --depth 1 https://github.com/rust-stuco/homeworks.git homeworks-temp
36+
37+
- name: Discover labs
38+
id: set-matrix
39+
run: |
40+
chmod +x .github/scripts/discover-labs.sh
41+
if [ -d "homeworks-temp" ]; then
42+
matrix=$(.github/scripts/discover-labs.sh)
43+
else
44+
# Use empty matrix to skip lab building
45+
matrix="[]"
46+
fi
47+
echo "matrix<<EOF" >> $GITHUB_OUTPUT
48+
echo "$matrix" >> $GITHUB_OUTPUT
49+
echo "EOF" >> $GITHUB_OUTPUT
50+
51+
# When homework files are cached (no changes in homeworks repo),
52+
# upload the cached files as an artifact. This is necessary because
53+
# build-labs and collect-labs jobs get skipped when matrix is empty,
54+
# but build-website still needs the homework files
55+
- name: Upload cached homework files
56+
if: steps.cache-homework-build.outputs.cache-hit == 'true'
57+
uses: actions/upload-artifact@v4
58+
with:
59+
name: homework-complete
60+
path: hw
61+
62+
build-labs:
63+
needs: discover-labs
64+
runs-on: ubuntu-latest
65+
if: needs.discover-labs.outputs.matrix != '[]'
66+
strategy:
67+
matrix:
68+
include: ${{fromJson(needs.discover-labs.outputs.matrix)}}
69+
steps:
70+
- name: Checkout repository
71+
uses: actions/checkout@v5
72+
73+
- name: Clone homeworks repository
74+
run: |
75+
git clone --depth 1 https://github.com/rust-stuco/homeworks.git homeworks-temp
76+
77+
- name: Get lab content hash
78+
id: lab-hash
79+
run: |
80+
lab_hash=$(find homeworks-temp/${{ matrix.week }}/${{ matrix.lab }} -type f \( -name "*.rs" -o -name "*.toml" -o -name "*.md" \) -exec sha256sum {} \; 2>/dev/null | sort | sha256sum | cut -d' ' -f1)
81+
echo "hash=$lab_hash" >> $GITHUB_OUTPUT
82+
83+
- name: Cache lab artifacts
84+
uses: actions/cache@v4
85+
with:
86+
path: hw/${{ matrix.lab }}
87+
key: lab-${{ matrix.lab }}-${{ steps.lab-hash.outputs.hash }}
88+
89+
- name: Setup Rust
90+
uses: actions-rust-lang/setup-rust-toolchain@v1
91+
with:
92+
toolchain: stable
93+
override: true
1294

13-
- name: big build
95+
- name: Build lab documentation
1496
run: |
15-
npm install
16-
npm run-script build
97+
chmod +x .github/scripts/build-lab.sh
98+
.github/scripts/build-lab.sh ${{ matrix.week }} ${{ matrix.lab }}
99+
100+
- name: Upload lab artifacts
101+
uses: actions/upload-artifact@v4
102+
with:
103+
name: ${{ matrix.lab }}
104+
path: hw/${{ matrix.lab }}
105+
106+
collect-labs:
107+
needs: [discover-labs, build-labs]
108+
runs-on: ubuntu-latest
109+
if: needs.discover-labs.outputs.matrix != '[]'
110+
steps:
111+
- name: Download all lab artifacts
112+
uses: actions/download-artifact@v5
113+
with:
114+
path: hw
115+
116+
- name: Reorganize artifacts
117+
run: |
118+
find hw -name "*.zip" -o -name "doc" -type d | while read item; do
119+
parent_dir=$(dirname "$item")
120+
lab_name=$(basename "$parent_dir")
121+
if [ "$parent_dir" != "hw/$lab_name" ]; then
122+
mkdir -p "hw/$lab_name"
123+
mv "$item" "hw/$lab_name/"
124+
fi
125+
done
126+
127+
- name: Cache complete homework build
128+
uses: actions/cache/save@v4
129+
with:
130+
path: hw
131+
key: homework-complete-${{ needs.discover-labs.outputs.homeworks-hash }}
132+
133+
- name: Upload complete homework artifacts
134+
uses: actions/upload-artifact@v4
135+
with:
136+
name: homework-complete
137+
path: hw
138+
139+
build-website:
140+
needs: [discover-labs, collect-labs]
141+
runs-on: ubuntu-latest
142+
if: always() && !cancelled()
143+
permissions:
144+
pages: write
145+
id-token: write
146+
environment:
147+
name: github-pages
148+
url: ${{ steps.deployment.outputs.page_url }}
149+
steps:
150+
- name: Checkout repository
151+
uses: actions/checkout@v5
152+
153+
- name: Clean existing homework folder
154+
run: rm -rf hw
155+
156+
- name: Download homework artifacts
157+
uses: actions/download-artifact@v5
158+
with:
159+
name: homework-complete
160+
path: hw
161+
continue-on-error: true
162+
163+
- name: Setup Bun
164+
uses: oven-sh/setup-bun@v2
165+
166+
- name: Build website
167+
run: |
168+
# Only set path prefix for forks
169+
if [ "${{ github.repository }}" != "rust-stuco/rust-stuco.github.io" ]; then
170+
export ELEVENTY_PATH_PREFIX="/${{ github.event.repository.name }}/"
171+
fi
172+
bun install
173+
bun run build
174+
175+
- name: Setup Pages
176+
uses: actions/configure-pages@v5
177+
178+
- name: Upload to GitHub Pages
179+
uses: actions/upload-pages-artifact@v4
180+
with:
181+
path: _site
17182

18-
- name: Push to gh-pages branch
19-
uses: s0/git-publish-subdir-action@develop
20-
env:
21-
REPO: self
22-
BRANCH: gh-pages # The branch name where you want to push the assets
23-
FOLDER: _site # The directory where your assets are generated
24-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub will automatically add this - you don't need to bother getting a token
25-
MESSAGE: "Build: ({sha}) {msg}" # The commit message
183+
- name: Deploy to GitHub Pages
184+
id: deployment
185+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules/
22
_site/
3-
.DS_Store
3+
.DS_Store
4+
homeworks-temp/

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1-
## Cool website
1+
# Rust StuCo Website
22

3-
To run this locally, do `npm install && npm run-script start`
3+
## Development
4+
5+
1. Generate local `hw` directory
6+
7+
```bash
8+
./scripts/generate-hw.sh
9+
```
10+
11+
2. Start project
12+
13+
```bash
14+
bun install
15+
bun run dev:11ty
16+
```

0 commit comments

Comments
 (0)