Skip to content

Fake update

Fake update #261

name: Generate Students Notebooks branch
on:
push:
branches: [main]
paths: ['**.ipynb']
workflow_dispatch:
defaults:
run:
shell: bash
permissions:
contents: write
actions: write
jobs:
process:
runs-on: ubuntu-latest
env:
CONFIG_PATH: .github/conversion.json
SUMMARY_FILE: /tmp/README.md
steps:
- name: Install Python dependencies
run: pip install chardet
- name: Initialize summary file
run: |
rm -f "$SUMMARY_FILE"
mkdir -p "$(dirname "$SUMMARY_FILE")"
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Validate JSON config
run: |
# JSON syntax validation with jq
if ! jq empty "$CONFIG_PATH" >/dev/null 2>&1; then
printf "## ❌ Error in JSON configuration file\n" >> $SUMMARY_FILE
printf "Please fix $CONFIG_PATH error:\n" >> $SUMMARY_FILE
jq empty "$CONFIG_PATH" 2>&1 | sed 's/^jq: //' >> $SUMMARY_FILE
exit 1
fi
npm install ajv@8
node - <<'EOF'
const fs = require('fs');
const Ajv = require('ajv').default;
const summaryFile = process.env.SUMMARY_FILE || '/tmp/README.md';
const configPath = process.env.CONFIG_PATH || '.github/conversion.json';
const schema = {
type: 'object',
required: [
'solution_marker', 'placeholder', 'generate_zip',
'notebooks_dir', 'student_postfix', 'tutor_postfix'
],
properties: {
solution_marker: {
type: 'object',
required: ['code', 'markdown'],
properties: { code: {type: 'string'}, markdown: {type: 'string'} },
additionalProperties: false
},
placeholder: {
type: 'object',
required: ['code', 'markdown'],
properties: { code: {type: 'string'}, markdown: {type: 'string'} },
additionalProperties: false
},
generate_zip: {type: 'boolean'},
notebooks_dir: {type: 'array', items: {type: 'string'}, minItems: 1},
pre_processing: {type: 'string'},
post_processing: {type: 'string'},
tutor_postfix: {type: 'string'},
student_postfix: {type: 'string'},
rebuild_all: {type: 'boolean'}
}
};
try {
const config = JSON.parse(fs.readFileSync(configPath));
const ajv = new Ajv({allErrors: true, strict: true});
const validate = ajv.compile(schema);
if (!validate(config)) {
const lines = [];
lines.push("## ❌ Error in JSON configuration file");
lines.push("Config validation failed:");
lines.push("```
validate.errors.forEach(err => {
lines.push(`- ${err.instancePath || '/'} ${err.message}`);
});
lines.push("```");
fs.appendFileSync(summaryFile, lines.join('\n') + '\n');
process.exit(1);
}
} catch (error) {
const lines = [];
lines.push("## ❌ Error in JSON configuration file");
lines.push("Parsing or validation failed:");
lines.push("```
lines.push(error.message);
lines.push("```");
fs.appendFileSync(summaryFile, lines.join('\n') + '\n');
process.exit(1);
}
EOF
- name: Check monitored directories existence
run: |
EXIT_WITH_ERROR=false
ERROR_HEADER_CREATED=false
while IFS= read -r dir; do
if [ ! -d "$dir" ]; then
if [ "$ERROR_HEADER_CREATED" = false ]; then
printf "## ❌ Error: Missing notebook directories\n" >> $SUMMARY_FILE
printf "The following directories specified in $CONFIG_PATH don't exist:\n" >> $SUMMARY_FILE
ERROR_HEADER_CREATED=true
fi
printf -- "* \`\`\`%s\`\`\`\n" "$dir" >> $SUMMARY_FILE
EXIT_WITH_ERROR=true
fi
done < <(jq -r '.notebooks_dir[]' "$CONFIG_PATH")
if [ "$EXIT_WITH_ERROR" = true ]; then
printf "\nPlease create these directories or update the configuration file.\n" >> $SUMMARY_FILE
exit 1
fi
- name: Store pre and post-processing command for future execution
run: |
echo "PRE_PROCESSING=$(jq -r '.pre_processing // empty' "$CONFIG_PATH")" >> $GITHUB_ENV
echo "POST_PROCESSING=$(jq -r '.post_processing // empty' "$CONFIG_PATH")" >> $GITHUB_ENV
- name: Check pre/post-processing commands syntax
run: |
# Use bash -n to check shell command syntax without execution
if [ -n "$PRE_PROCESSING" ]; then
ERROR_OUTPUT=$(echo "$PRE_PROCESSING" | bash -n 2>&1) || {
printf "## ❌ Error: Pre-processing command syntax error\n" >> $SUMMARY_FILE
printf "Please fix your pre-processing command syntax:\n" >> $SUMMARY_FILE
printf "%s\n" "$PRE_PROCESSING" >> $SUMMARY_FILE
printf "\n" >> $SUMMARY_FILE
printf "**Error details:**\n" >> $SUMMARY_FILE
printf "%s\n" "$ERROR_OUTPUT" >> $SUMMARY_FILE
exit 1
}
fi
if [ -n "$POST_PROCESSING" ]; then
ERROR_OUTPUT=$(echo "$POST_PROCESSING" | bash -n 2>&1) || {
printf "## ❌ Error: Post-processing command syntax error\n" >> $SUMMARY_FILE
printf "Please fix your post-processing command syntax:\n" >> $SUMMARY_FILE
printf "%s\n" "$POST_PROCESSING" >> $SUMMARY_FILE
printf "\n" >> $SUMMARY_FILE
printf "**Error details:**\n" >> $SUMMARY_FILE
printf "%s\n" "$ERROR_OUTPUT" >> $SUMMARY_FILE
exit 1
}
fi
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Setup uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
cache-dependency-glob: ".github/scripts/student_version.py"
- name: Execute pre-processing command
run: |
OUTPUT=$(bash -c "$PRE_PROCESSING" 2>&1)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
printf "## Pre-processing executed successfully ✅\n" >> $SUMMARY_FILE
if [ -n "$OUTPUT" ]; then
printf "%s\n" "$OUTPUT" >> $SUMMARY_FILE
else
printf "\n" >> $SUMMARY_FILE
fi
else
printf "## Post-processing failed ❌\n" >> $SUMMARY_FILE
printf "Exit code: %d\n" "$EXIT_CODE" >> $SUMMARY_FILE
if [ -n "$OUTPUT" ]; then
printf "\n" >> $SUMMARY_FILE
printf "Command output (including errors):\n" >> $SUMMARY_FILE
printf "%s\n" "$OUTPUT" >> $SUMMARY_FILE
fi
fi
- name: Prepare Students branch
run: |
git fetch origin Students || true
# Create or update Students branch as needed
git checkout Students || git checkout -b Students origin/Students || git checkout -b Students origin/main
git merge origin/main --strategy-option=theirs --allow-unrelated-histories || true
git push origin Students --force
if [ "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" ]; then
echo "STUDENTS_FRESHLY_CREATED=true" >> "$GITHUB_ENV"
else
echo "STUDENTS_FRESHLY_CREATED=false" >> "$GITHUB_ENV"
fi
- name: Detect changed notebooks
id: detect_notebooks
shell: bash
run: |
CONFIG_PATH=".github/conversion.json"
DIRS=$(jq -r '.notebooks_dir[]' "$CONFIG_PATH")
# Build patterns for target notebook files
PATTERNS=""
for dir in $DIRS; do
dir=$(echo "$dir" | sed 's:/*$::')
if [ -n "$PATTERNS" ]; then
PATTERNS+="|"
fi
PATTERNS+="^${dir}/.*\.ipynb$"
done
REBUILD_ALL=$(jq -r '.rebuild_all // false' "$CONFIG_PATH")
BEFORE=${{ github.event.before }}
AFTER=${{ github.event.after }}
echo "===== DEBUG DETECT NOTEBOOKS STEP ====="
echo "STUDENTS_FRESHLY_CREATED=\"$STUDENTS_FRESHLY_CREATED\""
echo "REBUILD_ALL=\"$REBUILD_ALL\""
echo "BEFORE=$BEFORE"
echo "AFTER=$AFTER"
echo "PATTERNS=\"$PATTERNS\""
echo "---------------"
if [[ "${STUDENTS_FRESHLY_CREATED}" == "true" || "$REBUILD_ALL" == "true" ]]; then
NOTEBOOKS_ON_MAIN=$(git ls-tree -r --name-only "$AFTER" | grep -E "$PATTERNS" || true)
echo "$NOTEBOOKS_ON_MAIN" > notebooks_to_convert.txt
echo "== FULL NOTEBOOKS LIST (FORCED)=="
echo "$NOTEBOOKS_ON_MAIN"
else
(git diff --name-only "$BEFORE" "$AFTER" | grep -E "$PATTERNS" || true) > notebooks_to_convert.txt
echo "== NOTEBOOKS FOUND BY DIFF =="
git diff --name-only "$BEFORE" "$AFTER" | grep -E "$PATTERNS" || true
fi
echo "CONTENTS OF notebooks_to_convert.txt:"
cat notebooks_to_convert.txt
echo "--- END DEBUG ---"
echo "notebooks<<EOF" >> $GITHUB_OUTPUT
cat notebooks_to_convert.txt >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Convert changed notebooks
run: |
printf "## Processing Report\n" >> $SUMMARY_FILE
printf "| Notebook | Questions | Code Blocks | ZIP |\n" >> $SUMMARY_FILE
printf "|----------|-----------|-------------|------|\n" >> $SUMMARY_FILE
echo "===== DEBUG CONVERT STEP ====="
echo "RAW NOTEBOOKS INPUT:"
echo "${{ steps.detect_notebooks.outputs.notebooks }}" | cat -A
echo "--- Starting conversion loop ---"
echo "${{ steps.detect_notebooks.outputs.notebooks }}" | while IFS= read -r nb; do
[ -z "$nb" ] && continue
echo "[DEBUG] Converting notebook: '$nb'"
git checkout origin/main -- "$nb"
uv run .github/scripts/student_version.py "$nb" \
--config "$CONFIG_PATH" \
--hide-header >> $SUMMARY_FILE
done
echo "--- END OF CONVERT STEP ---"
- name: Execute post-processing command
run: |
if [ -n "$POST_PROCESSING" ]; then
OUTPUT=$(bash -c "$POST_PROCESSING" 2>&1)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
printf "## Post-processing executed successfully ✅\n" >> $SUMMARY_FILE
if [ -n "$OUTPUT" ]; then
printf "%s\n" "$OUTPUT" >> $SUMMARY_FILE
else
printf "\n" >> $SUMMARY_FILE
fi
else
printf "## Post-processing failed ❌\n" >> $SUMMARY_FILE
printf "Exit code: %d\n" "$EXIT_CODE" >> $SUMMARY_FILE
if [ -n "$OUTPUT" ]; then
printf "\n" >> $SUMMARY_FILE
printf "Command output (including errors):\n" >> $SUMMARY_FILE
printf "%s\n" "$OUTPUT" >> $SUMMARY_FILE
fi
fi
fi
- name: Manage summary
run: |
cp -a $SUMMARY_FILE .
cat README.md >> $GITHUB_STEP_SUMMARY
- name: Set up Git identity
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "actions@github.com"
- name: Commit and push changes
run: |
git commit -m "Update student materials: $(date +'%Y-%m-%d %H:%M:%S')" || echo "No changes"
git push origin Students