Skip to content

fix(scorm): bake release version into the package so it's identifiabl…#7

Merged
RichardoC merged 1 commit into
mainfrom
stamp-with-version
Jul 14, 2026
Merged

fix(scorm): bake release version into the package so it's identifiabl…#7
RichardoC merged 1 commit into
mainfrom
stamp-with-version

Conversation

@RichardoC

Copy link
Copy Markdown
Owner

…e in an LMS (#7)

There was no way to tell which version of the course was running in an LMS -- the exported SCORM zip carried no build stamp, so two zips from different releases were indistinguishable once uploaded. Operators debugging "is this the version with the autosave fix?" had nothing to go on.

Root cause: nothing in source/data.xml or the export pipeline recorded the build version, and the release workflow (which knows the git tag at build time) did not inject it into the content before exporting.

Fix: a {{BUILD_VERSION}} placeholder committed in the course content, plus workflow steps that substitute it at build time. Two stamps land in every release zip:

  1. Visible in the player -- a new "Build" section on the About page (page 2) with

    Version: {{BUILD_VERSION}} ...

    . The token is a placeholder committed in source/data.xml + source/preview.xml.
  2. Machine-readable -- the release workflow adds a VERSION.txt (version, build timestamp, full commit SHA, source tree URL) to the zip root.

Why a placeholder (not a committed version): the version is only known at release time (the git tag), so it cannot be baked into committed source. The placeholder keeps source/data.xml version-agnostic.

Changes to source/data.xml + source/preview.xml (identical):

  • Added a "Build"

    section after the Provenance section on the About page, with a Version: {{BUILD_VERSION}} line. The placeholder value contains no XML-special characters and sits raw in the CDATA.

Release workflow (.github/workflows/release.yml):

  • "Compute build version" step: derives "v (YYYY-MM-DD, commit )" for release events (github.ref_name = tag) or "dev (..., workflow_dispatch)" for manual runs; exposes it via step outputs.
  • "Inject build version into course content" step: python3-replaces {{BUILD_VERSION}} in source/data.xml + source/preview.xml BEFORE the XOT import, so the substituted value is what gets exported. Asserts the placeholder is present (fails loudly if it was accidentally removed from source).
  • "Add VERSION.txt to the package" step: writes a VERSION.txt (version, build timestamp, commit SHA, source tree URL) and zips it into the package.
  • "Verify the package" step: now FAILS THE BUILD if {{BUILD_VERSION}} remains in the exported template.xml (guards against silent version-stamping regressions), and prints the substituted Version: line + VERSION.txt presence.

Preview workflow (.github/workflows/preview.yml):

  • "Set preview build label" step: substitutes {{BUILD_VERSION}} ->
    "preview (PR #N, commit )" in source/data.xml before render_preview.py, so PR preview HTML shows a clean build line instead of the raw token.

Validated end-to-end through a running XOT (docker-container branch) instance on host port 8088:

  • Pushed source/data.xml + source/preview.xml (with the placeholder) into the container; play.php?template_id=1 returns 200; HTML5 editor opens (200).
  • Editor Publish round-trip PRESERVES {{BUILD_VERSION}} intact in data.xml -- CKEditor does not mangle the braces, so editor-based edits are safe.
  • Simulated the release pipeline: substituted {{BUILD_VERSION}} -> "v0.0.6 (2026-07-14, commit abc1234)" in source/data.xml + source/preview.xml, pushed into XOT, play.php returned 200, re-exported SCORM. The exported template.xml shows "Version: v0.0.6 (2026-07-14, commit abc1234)" on the About page, 0 {{BUILD_VERSION}} placeholders remain, and a VERSION.txt was added to the zip root. All content/tracking attrs unchanged (45 questions, 80% pass, trackingMode="full", trackingWeight 1x7 + 21, unmarkForCompletion="true" x1, 0 empty options, 27 delaySecs="0", xPersistProgress autosave script present).
  • Ran the preview-workflow substitution script against a copy of source/data.xml: injected "preview (PR 7, commit abc1234)", 0 placeholders remain, render_preview.py renders the substituted line. Both workflow YAMLs parse; both heredoc scripts execute cleanly.

Trade-off: the placeholder is content that the release workflow mutates at build time (not a committed version), so a locally hand-built SCORM zip (without running the workflow) will show the literal {{BUILD_VERSION}} token on the About page and have no VERSION.txt. This is acceptable -- the documented deliverable path is the release workflow, which always substitutes. Do not remove the {{BUILD_VERSION}} placeholder from the About page without a replacement -- the release workflow's verify step expects it present before substitution and absent after, and that check guards against silent version-stamping regressions.

Guidance updates:

  • docs/PROJECT_CONTEXT.md: added "Build version stamping ({{BUILD_VERSION}} placeholder)" section documenting the two stamps, who substitutes the placeholder, why a placeholder, and the do-not-remove note; added build version greps to the verification checklist.
  • docs/COURSE_VERIFICATION.md: added "Build version stamping" section with the local validation results (substituted About-page line, 0 placeholders, VERSION.txt in zip, all attrs unchanged, Publish round-trip preserves the placeholder).

Generated with pi 0.80.6 and GLM 5.2

…e in an LMS (#7)

There was no way to tell which version of the course was running in an LMS --
the exported SCORM zip carried no build stamp, so two zips from different
releases were indistinguishable once uploaded. Operators debugging "is this
the version with the autosave fix?" had nothing to go on.

Root cause: nothing in source/data.xml or the export pipeline recorded the
build version, and the release workflow (which knows the git tag at build
time) did not inject it into the content before exporting.

Fix: a {{BUILD_VERSION}} placeholder committed in the course content, plus
workflow steps that substitute it at build time. Two stamps land in every
release zip:

1. Visible in the player -- a new "Build" section on the About page (page 2)
   with <p><strong>Version:</strong> {{BUILD_VERSION}} ...</p>. The token is
   a placeholder committed in source/data.xml + source/preview.xml.
2. Machine-readable -- the release workflow adds a VERSION.txt (version, build
   timestamp, full commit SHA, source tree URL) to the zip root.

Why a placeholder (not a committed version): the version is only known at
release time (the git tag), so it cannot be baked into committed source. The
placeholder keeps source/data.xml version-agnostic.

Changes to source/data.xml + source/preview.xml (identical):
- Added a "Build" <h2> section after the Provenance section on the About
  page, with a Version: {{BUILD_VERSION}} line. The placeholder value
  contains no XML-special characters and sits raw in the CDATA.

Release workflow (.github/workflows/release.yml):
- "Compute build version" step: derives "v<tag> (YYYY-MM-DD, commit <short>)"
  for release events (github.ref_name = tag) or "dev (..., workflow_dispatch)"
  for manual runs; exposes it via step outputs.
- "Inject build version into course content" step: python3-replaces
  {{BUILD_VERSION}} in source/data.xml + source/preview.xml BEFORE the XOT
  import, so the substituted value is what gets exported. Asserts the
  placeholder is present (fails loudly if it was accidentally removed from
  source).
- "Add VERSION.txt to the package" step: writes a VERSION.txt (version, build
  timestamp, commit SHA, source tree URL) and zips it into the package.
- "Verify the package" step: now FAILS THE BUILD if {{BUILD_VERSION}} remains
  in the exported template.xml (guards against silent version-stamping
  regressions), and prints the substituted Version: line + VERSION.txt
  presence.

Preview workflow (.github/workflows/preview.yml):
- "Set preview build label" step: substitutes {{BUILD_VERSION}} ->
  "preview (PR #N, commit <short>)" in source/data.xml before render_preview.py,
  so PR preview HTML shows a clean build line instead of the raw token.

Validated end-to-end through a running XOT (docker-container branch) instance
on host port 8088:
- Pushed source/data.xml + source/preview.xml (with the placeholder) into the
  container; play.php?template_id=1 returns 200; HTML5 editor opens (200).
- Editor Publish round-trip PRESERVES {{BUILD_VERSION}} intact in data.xml --
  CKEditor does not mangle the braces, so editor-based edits are safe.
- Simulated the release pipeline: substituted {{BUILD_VERSION}} -> "v0.0.6
  (2026-07-14, commit abc1234)" in source/data.xml + source/preview.xml,
  pushed into XOT, play.php returned 200, re-exported SCORM. The exported
  template.xml shows "Version:</strong> v0.0.6 (2026-07-14, commit abc1234)"
  on the About page, 0 {{BUILD_VERSION}} placeholders remain, and a
  VERSION.txt was added to the zip root. All content/tracking attrs unchanged
  (45 questions, 80% pass, trackingMode="full", trackingWeight 1x7 + 21,
  unmarkForCompletion="true" x1, 0 empty options, 27 delaySecs="0",
  xPersistProgress autosave script present).
- Ran the preview-workflow substitution script against a copy of
  source/data.xml: injected "preview (PR 7, commit abc1234)", 0 placeholders
  remain, render_preview.py renders the substituted line. Both workflow YAMLs
  parse; both heredoc scripts execute cleanly.

Trade-off: the placeholder is content that the release workflow mutates at
build time (not a committed version), so a locally hand-built SCORM zip
(without running the workflow) will show the literal {{BUILD_VERSION}} token
on the About page and have no VERSION.txt. This is acceptable -- the
documented deliverable path is the release workflow, which always substitutes.
Do not remove the {{BUILD_VERSION}} placeholder from the About page without a
replacement -- the release workflow's verify step expects it present before
substitution and absent after, and that check guards against silent
version-stamping regressions.

Guidance updates:
- docs/PROJECT_CONTEXT.md: added "Build version stamping ({{BUILD_VERSION}}
  placeholder)" section documenting the two stamps, who substitutes the
  placeholder, why a placeholder, and the do-not-remove note; added build
  version greps to the verification checklist.
- docs/COURSE_VERIFICATION.md: added "Build version stamping" section with
  the local validation results (substituted About-page line, 0 placeholders,
  VERSION.txt in zip, all attrs unchanged, Publish round-trip preserves the
  placeholder).

Generated with pi 0.80.6 and GLM 5.2
@github-actions

Copy link
Copy Markdown

📖 Course content preview

Download the course-preview artifact from the workflow run and open index.html to read the full course (pages + quizzes, correct answers marked ✓):

This preview is generated from source/data.xml by tools/render_preview.py. It is for review only — the playable SCORM package is built by the release workflow.

@RichardoC
RichardoC merged commit 06097fa into main Jul 14, 2026
1 check passed
@RichardoC
RichardoC deleted the stamp-with-version branch July 14, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant