Skip to content

Conversation

@davidsbailey
Copy link
Member

We've had 2 instances of a stable course inexplicably changing to in_development as part of a levelbuilder scoop:

  1. https://codedotorg.slack.com/archives/C08AMQ869QX/p1758733641359819
  2. https://codedotorg.slack.com/archives/C0T0PNTM3/p1766009860842969?thread_ts=1766005007.765299&cid=C0T0PNTM3

In the second case, the AIF 2025 course was unpublished in production and became unavailable to end users.

This PR adds a validation specifically to give an error if a stable course changes to in_development again in any environment. this serves a few purposes:

  • try and catch the levelbuilder machine in the act of unpublishing a course, as a way to narrow down where the bug is occurring
  • if a course json file does end up reflecting the unwanted change of published state, this same validation will fail the deploy during the seed step on staging and production, preventing the issue from reaching our end users.

Testing story

I am relying on existing test coverage to ensure this doesn't break any flows we care about. I'm open to other checks to perform before shipping this if any reviewers have specific ideas.

@davidsbailey davidsbailey marked this pull request as ready for review December 18, 2025 21:18
validates :link, presence: true
validates :published_state, acceptance: {accept: Curriculum::SharedCourseConstants::PUBLISHED_STATE.to_h.values, message: 'must be in_development, pilot, beta, preview or stable'}
validate :validate_family_name_and_version_year
validate :prevent_unlaunch_stable_courses
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do sometimes need to move curriculum back into in_development so curriculum writers can make changes. How does this validation affect that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this provide enough detail?

  # In the case where you really do want to unpublish a course, such as to allow
  # curriculum writers to make edits to the course on levelbuilder, you can work
  # around this validation by first changing the published_state to another
  # state before changing it to in_development.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we could just do validate: false as well 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went to update the comment, but then I realized that .save(validate: false) and .update_columns are slightly riskier because they skip other validations, such as ensuring that the new value is a valid published state and not a misspelling like development. People who know about the other shortcuts can still feel free to use them at their own risk. Let's try going with what we have here and we can update it later if it becomes a stumbling block.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we want to make this more dev-user-friendly in the future, one idea would be to add an attribute like our existing skip_name_format_validation, so that it can be inlined into an update! call and also preserve existing validations.

@davidsbailey davidsbailey merged commit 3dc9059 into staging Jan 7, 2026
7 checks passed
@davidsbailey davidsbailey deleted the prevent-course-unlaunch branch January 7, 2026 03:17
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.

2 participants