Skip to content

Delete Course Data

Delete Course Data #2

Workflow file for this run

name: Delete Course Data
on:
workflow_dispatch:
inputs:
course_ids:
description: "Course ID(s) to delete, comma-separated (e.g. 30004 or 30004,30005)"
required: true
type: string
sub_ids:
description: "Optional lecture sub_id(s) to delete within the course (comma-separated). If omitted, deletes the entire course."
required: false
type: string
default: ""
permissions:
contents: write
concurrency:
group: db-reset
cancel-in-progress: false
jobs:
delete:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install pycryptodome
- name: Fetch and decrypt database
env:
STUID: ${{ secrets.STUID }}
UISPSW: ${{ secrets.UISPSW }}
run: |
git fetch origin data --depth=1
mkdir -p data/sharded/shards
if git cat-file -e origin/data:data/icourse-index.enc 2>/dev/null; then
git show origin/data:data/icourse-index.enc > data/sharded/icourse-index.enc
shard_paths=$(git ls-tree -r --name-only origin/data | grep '^data/shards/' || true)
for path in $shard_paths; do
base=$(basename "$path")
git show "origin/data:$path" > "data/sharded/shards/$base"
done
python scripts/db_shard.py reassemble data/sharded data/icourse.db
else
echo "::error::No sharded database found on data branch."
exit 1
fi
- name: Delete lecture(s) or course(s)
run: |
SUB_IDS="${{ inputs.sub_ids }}"
IFS=',' read -ra CIDS <<< "${{ inputs.course_ids }}"
for cid in "${CIDS[@]}"; do
cid=$(echo "$cid" | xargs)
if [ -n "$SUB_IDS" ]; then
echo "Deleting specific lecture(s) from course $cid..."
IFS=',' read -ra SIDS <<< "$SUB_IDS"
for sid in "${SIDS[@]}"; do
sid=$(echo "$sid" | xargs)
echo " Deleting lecture $sid..."
sqlite3 data/icourse.db "DELETE FROM ppt_pages WHERE sub_id='$sid'"
sqlite3 data/icourse.db "DELETE FROM lectures WHERE sub_id='$sid'"
done
remaining=$(sqlite3 data/icourse.db "SELECT COUNT(*) FROM lectures WHERE course_id='$cid'")
echo " $remaining lecture(s) remaining for course $cid"
if [ "$remaining" -eq 0 ]; then
sqlite3 data/icourse.db "DELETE FROM courses WHERE course_id='$cid'"
echo " Course $cid removed (no lectures left)"
fi
else
echo "Deleting entire course $cid..."
count=$(sqlite3 data/icourse.db "SELECT COUNT(*) FROM lectures WHERE course_id='$cid'")
sqlite3 data/icourse.db "DELETE FROM ppt_pages WHERE sub_id IN (SELECT sub_id FROM lectures WHERE course_id='$cid')"
sqlite3 data/icourse.db "DELETE FROM lectures WHERE course_id='$cid'"
sqlite3 data/icourse.db "DELETE FROM courses WHERE course_id='$cid'"
echo " Removed $count lecture(s) for course $cid"
fi
done
# NOTE: COURSE_IDS is deliberately NOT touched here. GitHub's
# Secrets API is write-only (values can never be read back), so a
# workflow cannot remove one ID from the list. The frontend's
# subscription editor owns that secret — it re-encrypts and PUTs
# the full list whenever the user changes their subscription.
- name: Re-shard and push
env:
STUID: ${{ secrets.STUID }}
UISPSW: ${{ secrets.UISPSW }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Shard into a fresh directory — data/sharded still holds the
# fetched pre-delete shard files, and a deleted course's shard
# must not survive into the push.
rm -rf data/sharded_out
mkdir -p data/sharded_out
python scripts/db_shard.py shard data/icourse.db data/sharded_out
# data/ is gitignored in the source tree and the data branch has
# unrelated history, so stage to a clean tree and force-push —
# the same pattern check.yml / single_run.yml use.
rm -rf /tmp/db_deploy
mkdir -p /tmp/db_deploy/data/shards
cp data/sharded_out/icourse-index.enc /tmp/db_deploy/data/
cp data/sharded_out/shards/*.db.gz.enc /tmp/db_deploy/data/shards/
cd /tmp/db_deploy
git init -q
git checkout -q -b data
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add data/
git commit -q -m "chore: delete ${{ inputs.sub_ids != '' && 'lecture(s)' || 'course(s)' }} ${{ inputs.sub_ids || inputs.course_ids }}"
git remote add origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git"
git push --force origin data