Skip to content

Commit d2c8c44

Browse files
authored
Merge pull request #5 from TUBAF-IfI-LiaScript/copilot/compare-action-makefile-functionality
Fix stale upstream PDFs and centralize course→repo mapping
2 parents b1861e3 + 4c7f7f6 commit d2c8c44

9 files changed

Lines changed: 683 additions & 223 deletions

File tree

.github/workflows/generateOERoverview.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ jobs:
3434

3535
- name: Generate missing course websites
3636
if: steps.changes.outputs.courses_to_generate != ''
37+
env:
38+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3739
run: bash scripts/generate_courses.sh "${{ steps.changes.outputs.courses_to_generate }}"
3840

3941
- name: Display deployment summary

Makefile

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ $(1): $(1).yml
1515
$(MAKE) force-build-$(1); \
1616
else \
1717
echo "📄 Using existing $(1).html and assets"; \
18+
$(MAKE) download-pdfs-$(1); \
1819
fi
1920

20-
force-build-$(1): clean-$(1) build-$(1) organize-$(1) update-cache-$(1) mark-changed
21+
force-build-$(1): clean-$(1) download-pdfs-$(1) build-$(1) organize-$(1) update-cache-$(1) mark-changed
2122

2223
clean-$(1):
2324
@echo "🧹 Cleaning old files for $(1)..."
@@ -28,8 +29,14 @@ clean-$(1):
2829

2930
build-$(1):
3031
$(if $(filter $(1),$(PDF_COURSES)), \
31-
liaex --input $(1).yml --output $(1) --format project --project-generate-pdf --scorm-organization $(SCORM_ORG) --scorm-embed --scorm-masteryScore $(SCORM_SCORE), \
32-
liaex --input $(1).yml --output $(1) --format project)
32+
if [ -f ".cache/$(1)_skip_pdf_gen" ]; then \
33+
echo "🔨 Building $(1) (all PDFs from upstream)..."; \
34+
liaex --input $(1).yml --output $(1) --format project --scorm-organization $(SCORM_ORG) --scorm-embed --scorm-masteryScore $(SCORM_SCORE) --project-category-blur; \
35+
else \
36+
echo "🔨 Building $(1) with PDF generation..."; \
37+
liaex --input $(1).yml --output $(1) --format project --project-generate-pdf --scorm-organization $(SCORM_ORG) --scorm-embed --scorm-masteryScore $(SCORM_SCORE) --project-category-blur; \
38+
fi, \
39+
liaex --input $(1).yml --output $(1) --format project --project-category-blur)
3340

3441
organize-$(1):
3542
$(if $(filter $(1),$(PDF_COURSES)), \
@@ -39,19 +46,41 @@ endef
3946
# Generate targets for all courses
4047
$(foreach course,$(COURSES),$(eval $(call build_course,$(course))))
4148

49+
# Download upstream release PDFs for a single course.
50+
# Creates .cache/<course>_skip_pdf_gen when all lessons are covered by upstream PDFs.
51+
download-pdfs-%:
52+
@if [ -n "$(filter $*,$(PDF_COURSES))" ]; then \
53+
mkdir -p .cache; \
54+
[ -x scripts/download_upstream_pdfs.sh ] || chmod +x scripts/download_upstream_pdfs.sh; \
55+
LESSON_COUNT=$$(grep -c '^[[:space:]]*- url:' "$*.yml" 2>/dev/null) || LESSON_COUNT=0; \
56+
if bash scripts/download_upstream_pdfs.sh "$*"; then \
57+
if [ -f ".cache/$*_upstream_pdfs" ]; then \
58+
UPSTREAM_COUNT=$$(wc -l < ".cache/$*_upstream_pdfs" | tr -d ' '); \
59+
else \
60+
UPSTREAM_COUNT=0; \
61+
fi; \
62+
if [ "$$UPSTREAM_COUNT" -ge "$$LESSON_COUNT" ] && [ "$$LESSON_COUNT" -gt 0 ]; then \
63+
touch ".cache/$*_skip_pdf_gen"; \
64+
echo "✅ All $$UPSTREAM_COUNT upstream PDFs present for $* – PDF generation will be skipped"; \
65+
else \
66+
rm -f ".cache/$*_skip_pdf_gen"; \
67+
echo "📄 $$UPSTREAM_COUNT/$$LESSON_COUNT upstream PDFs for $* – PDF generation needed"; \
68+
fi; \
69+
else \
70+
rm -f ".cache/$*_skip_pdf_gen"; \
71+
echo "📄 No upstream PDFs for $* – PDF generation needed"; \
72+
fi; \
73+
fi
74+
75+
# Download upstream PDFs for all PDF courses (useful for local mode: make download-pdfs)
76+
download-pdfs: $(foreach course,$(PDF_COURSES),download-pdfs-$(course))
77+
4278
mark-changed:
4379
@touch .cache/build_occurred
4480

4581
update-cache-%:
4682
@YAML_HASH=$$(sha256sum $*.yml 2>/dev/null | cut -d' ' -f1 || echo "missing"); \
47-
case "$*" in \
48-
"digitalesysteme") REPO_NAME="EingebetteteSysteme" ;; \
49-
"prozprog") REPO_NAME="ProzeduraleProgrammierung" ;; \
50-
"softwareentwicklung") REPO_NAME="Softwareentwicklung" ;; \
51-
"robotikprojekt") REPO_NAME="SoftwareprojektRobotik" ;; \
52-
"index") REPO_NAME="" ;; \
53-
*) REPO_NAME="" ;; \
54-
esac; \
83+
REPO_NAME=$$(bash scripts/courses_lib.sh '$*' || true); \
5584
if [ -n "$$REPO_NAME" ]; then \
5685
API_URL="https://api.github.com/repos/TUBAF-IfI-LiaScript/VL_$${REPO_NAME}/commits/master"; \
5786
API_RESPONSE=$$(curl -sL --connect-timeout 10 "$$API_URL" 2>/dev/null); \
@@ -156,11 +185,11 @@ status:
156185
else \
157186
echo " 📁 No assets"; \
158187
fi; \
159-
repo_name=$$(echo $$course | sed 's/digitalesysteme/EingebetteteSysteme/;s/prozprog/ProzeduraleProgrammierung/;s/softwareentwicklung/Softwareentwicklung/;s/robotikprojekt/SoftwareprojektRobotik/;s/index/INDEX_SKIP/'); \
160-
if [ "$$repo_name" != "INDEX_SKIP" ]; then \
188+
repo_name=$$(bash scripts/courses_lib.sh "$$course" || true); \
189+
if [ -n "$$repo_name" ]; then \
161190
echo " 🌐 Monitoring: VL_$$repo_name"; \
162191
else \
163-
echo " 🌐 No remote monitoring (index)"; \
192+
echo " 🌐 No remote monitoring"; \
164193
fi; \
165194
done
166195

@@ -173,6 +202,7 @@ help:
173202
@echo " status - Show build status of all courses"
174203
@echo " git-update - Update git repository"
175204
@echo " prune-pdfs - Remove PDFs not referenced by any HTML"
205+
@echo " download-pdfs - Download upstream release PDFs for all PDF courses"
176206
@echo ""
177207
@echo "Individual courses (with change detection):"
178208
@$(foreach course,$(COURSES),echo " $(course)";)
@@ -185,7 +215,7 @@ help:
185215
@echo " SCORM org: $(SCORM_ORG)"
186216
@echo " SCORM score: $(SCORM_SCORE)"
187217

188-
.PHONY: all clean-all clean-cache force-all status git-update help prune-pdfs $(COURSES)
218+
.PHONY: all clean-all clean-cache force-all status git-update help prune-pdfs download-pdfs $(COURSES)
189219

190220
prune-pdfs:
191221
@echo "🗑️ Pruning unreferenced PDFs..."

scripts/check_changes.sh

Lines changed: 114 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -9,106 +9,130 @@ if [ -z "$COURSE" ]; then
99
exit 1
1010
fi
1111

12-
# Create cache directory
13-
mkdir -p .cache
14-
1512
# File paths
1613
YAML_FILE="${COURSE}.yml"
1714
HTML_FILE="${COURSE}.html"
1815
CACHE_FILE=".cache/${COURSE}"
1916

20-
# Check if YAML file exists
21-
if [ ! -f "$YAML_FILE" ]; then
22-
echo "❌ YAML file $YAML_FILE not found"
23-
exit 1
24-
fi
17+
# Get remote repository name from central config via shared library
18+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19+
# shellcheck source=courses_lib.sh
20+
. "${SCRIPT_DIR}/courses_lib.sh"
2521

26-
# Calculate YAML hash
27-
YAML_HASH=$(sha256sum "$YAML_FILE" 2>/dev/null | cut -d' ' -f1 || echo "missing")
28-
29-
# Get remote repository hash
30-
case "$COURSE" in
31-
"digitalesysteme")
32-
REPO_NAME="EingebetteteSysteme"
33-
;;
34-
"prozprog")
35-
REPO_NAME="ProzeduraleProgrammierung"
36-
;;
37-
"softwareentwicklung")
38-
REPO_NAME="Softwareentwicklung"
39-
;;
40-
"robotikprojekt")
41-
REPO_NAME="SoftwareprojektRobotik"
42-
;;
43-
"index")
44-
REPO_NAME="" # No remote monitoring for index
45-
;;
46-
*)
47-
REPO_NAME=""
48-
;;
49-
esac
50-
51-
if [ -n "$REPO_NAME" ]; then
52-
echo "🌐 Checking VL_${REPO_NAME} repository..."
53-
API_URL="https://api.github.com/repos/TUBAF-IfI-LiaScript/VL_${REPO_NAME}/commits/master"
54-
55-
# Try jq first (more reliable), fallback to grep
56-
# Use -L to follow redirects (in case repository was renamed/moved)
57-
API_RESPONSE=$(curl -sL --connect-timeout 10 "$API_URL" 2>/dev/null)
58-
59-
if command -v jq >/dev/null 2>&1; then
60-
REMOTE_HASH=$(echo "$API_RESPONSE" | jq -r '.sha' 2>/dev/null || echo "unreachable")
61-
else
62-
REMOTE_HASH=$(echo "$API_RESPONSE" | sed -n 's/.*"sha":"\([^"]*\)".*/\1/p' | head -1)
63-
if [ -z "$REMOTE_HASH" ]; then
22+
# ---------------------------------------------------------------------------
23+
# init – create required directories
24+
# ---------------------------------------------------------------------------
25+
init() {
26+
mkdir -p .cache
27+
if [ ! -f "$YAML_FILE" ]; then
28+
echo "❌ YAML file $YAML_FILE not found"
29+
exit 1
30+
fi
31+
}
32+
33+
# ---------------------------------------------------------------------------
34+
# get_yaml_hash – compute SHA-256 hash of the course YAML file.
35+
# Sets YAML_HASH.
36+
# ---------------------------------------------------------------------------
37+
get_yaml_hash() {
38+
YAML_HASH=$(sha256sum "$YAML_FILE" 2>/dev/null | cut -d' ' -f1 || echo "missing")
39+
}
40+
41+
# ---------------------------------------------------------------------------
42+
# get_remote_hash – fetch the latest commit SHA from the upstream repository.
43+
# Sets REMOTE_HASH.
44+
# ---------------------------------------------------------------------------
45+
get_remote_hash() {
46+
REPO_NAME=$(lookup_repo "$COURSE")
47+
48+
if [ -n "$REPO_NAME" ]; then
49+
echo "🌐 Checking VL_${REPO_NAME} repository..."
50+
API_URL="https://api.github.com/repos/TUBAF-IfI-LiaScript/VL_${REPO_NAME}/commits/master"
51+
52+
# Use -L to follow redirects (in case repository was renamed/moved)
53+
API_RESPONSE=$(curl -sL --connect-timeout 10 "$API_URL" 2>/dev/null)
54+
55+
if command -v jq >/dev/null 2>&1; then
56+
REMOTE_HASH=$(echo "$API_RESPONSE" | jq -r '.sha' 2>/dev/null || echo "unreachable")
57+
else
58+
REMOTE_HASH=$(echo "$API_RESPONSE" | sed -n 's/.*"sha":"\([^"]*\)".*/\1/p' | head -1)
59+
if [ -z "$REMOTE_HASH" ]; then
60+
REMOTE_HASH="unreachable"
61+
fi
62+
fi
63+
64+
if [ "$REMOTE_HASH" = "unreachable" ] || [ -z "$REMOTE_HASH" ]; then
65+
echo "⚠️ Failed to get remote hash"
6466
REMOTE_HASH="unreachable"
6567
fi
68+
else
69+
REMOTE_HASH="no-remote"
6670
fi
67-
68-
if [ "$REMOTE_HASH" = "unreachable" ] || [ -z "$REMOTE_HASH" ]; then
69-
echo "⚠️ Failed to get remote hash"
70-
REMOTE_HASH="unreachable"
71+
}
72+
73+
# ---------------------------------------------------------------------------
74+
# read_cache – load previously stored hashes from cache file.
75+
# Sets CACHED_YAML and CACHED_REMOTE.
76+
# ---------------------------------------------------------------------------
77+
read_cache() {
78+
if [ -f "$CACHE_FILE" ]; then
79+
CACHED_YAML=$(sed -n '1p' "$CACHE_FILE" 2>/dev/null || echo "missing")
80+
CACHED_REMOTE=$(sed -n '2p' "$CACHE_FILE" 2>/dev/null || echo "missing")
81+
else
82+
CACHED_YAML="missing"
83+
CACHED_REMOTE="missing"
7184
fi
72-
else
73-
REMOTE_HASH="no-remote"
74-
fi
85+
}
7586

76-
# Read cached values
77-
if [ -f "$CACHE_FILE" ]; then
78-
CACHED_YAML=$(sed -n '1p' "$CACHE_FILE" 2>/dev/null || echo "missing")
79-
CACHED_REMOTE=$(sed -n '2p' "$CACHE_FILE" 2>/dev/null || echo "missing")
80-
else
81-
CACHED_YAML="missing"
82-
CACHED_REMOTE="missing"
83-
fi
87+
# ---------------------------------------------------------------------------
88+
# print_status – display current vs. cached hash values.
89+
# ---------------------------------------------------------------------------
90+
print_status() {
91+
echo "📄 YAML hash: ${YAML_HASH:0:8}..."
92+
echo "🌐 Remote hash: ${REMOTE_HASH:0:8}..."
93+
echo "💾 Cached YAML: ${CACHED_YAML:0:8}..."
94+
echo "💾 Cached remote: ${CACHED_REMOTE:0:8}..."
95+
}
8496

85-
# Display status
86-
echo "📄 YAML hash: ${YAML_HASH:0:8}..."
87-
echo "🌐 Remote hash: ${REMOTE_HASH:0:8}..."
88-
echo "💾 Cached YAML: ${CACHED_YAML:0:8}..."
89-
echo "💾 Cached remote: ${CACHED_REMOTE:0:8}..."
90-
91-
# Check for changes
92-
REBUILD_NEEDED=false
93-
REASON=""
94-
95-
if [ "$YAML_HASH" != "$CACHED_YAML" ]; then
96-
REBUILD_NEEDED=true
97-
REASON="YAML file changed"
98-
elif [ "$REMOTE_HASH" != "$CACHED_REMOTE" ] && [ "$REMOTE_HASH" != "unreachable" ]; then
99-
REBUILD_NEEDED=true
100-
REASON="Remote repository changed"
101-
elif [ ! -f "$HTML_FILE" ]; then
102-
REBUILD_NEEDED=true
103-
REASON="HTML file missing"
104-
fi
97+
# ---------------------------------------------------------------------------
98+
# check_rebuild_needed – determine if a rebuild is required.
99+
# Exits 0 if rebuild needed, exits 1 if no rebuild needed.
100+
# ---------------------------------------------------------------------------
101+
check_rebuild_needed() {
102+
local rebuild_needed=false
103+
local reason=""
104+
105+
if [ "$YAML_HASH" != "$CACHED_YAML" ]; then
106+
rebuild_needed=true
107+
reason="YAML file changed"
108+
elif [ "$REMOTE_HASH" != "$CACHED_REMOTE" ] && [ "$REMOTE_HASH" != "unreachable" ]; then
109+
rebuild_needed=true
110+
reason="Remote repository changed"
111+
elif [ ! -f "$HTML_FILE" ]; then
112+
rebuild_needed=true
113+
reason="HTML file missing"
114+
fi
115+
116+
if [ "$rebuild_needed" = true ]; then
117+
echo "$reason - rebuild needed"
118+
# Note: Cache will be updated by the build system after successful build
119+
exit 0 # Rebuild needed
120+
else
121+
echo "⏭️ No changes detected - skipping"
122+
exit 1 # No rebuild needed
123+
fi
124+
}
125+
126+
# ---------------------------------------------------------------------------
127+
# main
128+
# ---------------------------------------------------------------------------
129+
main() {
130+
init
131+
get_yaml_hash
132+
get_remote_hash
133+
read_cache
134+
print_status
135+
check_rebuild_needed
136+
}
105137

106-
# Output result
107-
if [ "$REBUILD_NEEDED" = true ]; then
108-
echo "$REASON - rebuild needed"
109-
# Note: Cache will be updated by the build system after successful build
110-
exit 0 # Rebuild needed
111-
else
112-
echo "⏭️ No changes detected - skipping"
113-
exit 1 # No rebuild needed
114-
fi
138+
main

scripts/courses.conf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Central course → upstream repository mapping
2+
# Format: course_name:upstream_repo_suffix
3+
# The full upstream repo is: TUBAF-IfI-LiaScript/VL_<upstream_repo_suffix>
4+
#
5+
# Add a new line here to register a course for upstream PDF downloads and
6+
# remote-change detection. Courses not listed here are treated as local-only
7+
# (no upstream repo monitoring, no upstream PDF download).
8+
9+
digitalesysteme:EingebetteteSysteme
10+
prozprog:ProzeduraleProgrammierung
11+
softwareentwicklung:Softwareentwicklung
12+
robotikprojekt:SoftwareprojektRobotik

scripts/courses_lib.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
# Shared helper library for courses.conf lookups.
3+
#
4+
# When sourced:
5+
# . scripts/courses_lib.sh
6+
# repo=$(lookup_repo "$course") # prints repo suffix, or empty string
7+
#
8+
# When executed directly:
9+
# scripts/courses_lib.sh <course_name> # prints repo suffix, or empty string
10+
11+
# Locate courses.conf relative to this script regardless of working directory.
12+
_COURSES_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13+
COURSES_CONF="${_COURSES_LIB_DIR}/courses.conf"
14+
15+
# lookup_repo <course_name>
16+
# Prints the upstream repository suffix for the given course name, or an empty
17+
# string when the course has no upstream mapping.
18+
lookup_repo() {
19+
local course="$1"
20+
grep -v '^[[:space:]]*#' "${COURSES_CONF}" | grep "^${course}:" | cut -d: -f2 | tr -d '[:space:]' || true
21+
}
22+
23+
# When this file is executed directly (not sourced) it acts as a thin
24+
# command-line wrapper so Makefiles and other callers can use it without
25+
# needing to source it.
26+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
27+
if [ -z "${1:-}" ]; then
28+
echo "Usage: $0 <course_name>" >&2
29+
exit 1
30+
fi
31+
lookup_repo "$1"
32+
fi

0 commit comments

Comments
 (0)