Summary
When creating a student repository, automatically create all daily issues from the daily_issues/ directory of the teaching material GitLab repo. Issues are created once during setup — no separate scheduling, no tracking table.
Addresses #22. Depends on #77 and #78.
Context
Teaching Material Issue Templates
daily_issues/
day1_git_basics.md
day1_software_engineering_1.md
day1_swiftui_1.md
day2_software_engineering_2_aom.md
day2_software_engineering_2_glossary.md
day2_software_engineering_2_product_backlog.md
day3_software_engineering_3.md
day4_software_engineering_4_component.md
Each file is Markdown: first # heading is the issue title, everything else is the description.
Changes
1. Parse Issue Templates
Fetch and parse issue files from the teaching material repo (same gitlabClient, same token):
type IssueTemplate struct {
Identifier string // "day1_git_basics" (filename without .md)
Title string // extracted from first # heading
Description string // everything after the title
}
func parseIssueTemplates(files []TemplateFile) []IssueTemplate {
// Filter for daily_issues/*.md
// Split on first "# " line → title
// Remaining content → description
// Sort by filename (day1 before day2, etc.)
}
2. Create Issues During Student Setup
After pushing template files, create all issues:
func (s *InfrastructureService) createStudentIssues(projectID int64) error {
templates, err := s.fetchIssueTemplates()
if err != nil {
return fmt.Errorf("failed to fetch issue templates: %w", err)
}
for _, tmpl := range templates {
_, _, err := s.gitlabClient.Issues.CreateIssue(projectID, &gitlab.CreateIssueOptions{
Title: gitlab.Ptr(tmpl.Title),
Description: gitlab.Ptr(tmpl.Description),
})
if err != nil {
// Log and continue — one failed issue should not block the others
log.WithField("issue", tmpl.Identifier).Error("failed to create issue: ", err)
continue
}
}
return nil
}
3. Idempotency via GitLab Check (No Tracking Table)
On re-run, check GitLab directly for existing issues by title:
// Before creating, check if issue with same title already exists
existingIssues, _, _ := s.gitlabClient.Issues.ListProjectIssues(projectID, &gitlab.ListProjectIssuesOptions{
Search: gitlab.Ptr(tmpl.Title),
})
for _, existing := range existingIssues {
if existing.Title == tmpl.Title {
// Already exists, skip
continue
}
}
No student_issue_tracking table. GitLab is the source of truth for what issues exist. Duplicating this state in Postgres creates staleness risk for zero benefit. If you need to know which issues were created by PROMPT vs. by the student, the title match is sufficient — course issues have structured titles like "Day 1: Create Problem Statement..."
4. Cache Issue Templates
Issue templates are fetched alongside template files (from #78). Use the same caching pattern: fetch once per server lifetime.
Deletion Considerations (Future, Out of Scope)
If issue deletion is ever needed, note:
- Students create their own issues (user stories, backlog items)
- Never delete all issues — only delete issues matching the exact titles from the templates
- Check for student activity (comments, status changes, linked MRs) before deleting
- This is inherently dangerous and should require explicit confirmation
Acceptance Criteria
Out of Scope
student_issue_tracking table (not needed — GitLab is source of truth)
- Day-by-day scheduling (all created at once)
- Issue deletion
- Issue labels/milestones
- Late student catch-up (handled by re-running setup, which creates missing issues)
Summary
When creating a student repository, automatically create all daily issues from the
daily_issues/directory of the teaching material GitLab repo. Issues are created once during setup — no separate scheduling, no tracking table.Addresses #22. Depends on #77 and #78.
Context
Teaching Material Issue Templates
Each file is Markdown: first
# headingis the issue title, everything else is the description.Changes
1. Parse Issue Templates
Fetch and parse issue files from the teaching material repo (same
gitlabClient, same token):2. Create Issues During Student Setup
After pushing template files, create all issues:
3. Idempotency via GitLab Check (No Tracking Table)
On re-run, check GitLab directly for existing issues by title:
No
student_issue_trackingtable. GitLab is the source of truth for what issues exist. Duplicating this state in Postgres creates staleness risk for zero benefit. If you need to know which issues were created by PROMPT vs. by the student, the title match is sufficient — course issues have structured titles like "Day 1: Create Problem Statement..."4. Cache Issue Templates
Issue templates are fetched alongside template files (from #78). Use the same caching pattern: fetch once per server lifetime.
Deletion Considerations (Future, Out of Scope)
If issue deletion is ever needed, note:
Acceptance Criteria
daily_issues/(title from# heading)Out of Scope
student_issue_trackingtable (not needed — GitLab is source of truth)