Skip to content

[Tooling] Upload CDN builds as drafts, publish in publish_release#2695

Draft
iangmaia wants to merge 3 commits intotrunkfrom
iangmaia/upload-cdn-builds-as-internal-first
Draft

[Tooling] Upload CDN builds as drafts, publish in publish_release#2695
iangmaia wants to merge 3 commits intotrunkfrom
iangmaia/upload-cdn-builds-as-internal-first

Conversation

@iangmaia
Copy link
Contributor

@iangmaia iangmaia commented Mar 3, 2026

Related issues

How AI was used in this PR

Claude Code was used to implement the Fastfile changes based on a detailed plan I designed. I reviewed all generated code.

Proposed Changes

  • Upload all non-beta CDN builds as drafts with external visibility (previously published immediately), so they're not publicly accessible during the testing period
  • Beta builds continue to be published immediately (no post_status: 'draft')
  • Add make_cdn_builds_public helper that queries the CDN API via list_apps_cdn_builds to find draft builds for the release version, then publishes each via update_apps_cdn_build_metadata
  • Call make_cdn_builds_public in publish_release before publishing the GitHub release
  • Update finalize_release prompt to mention the new draft behavior

Why drafts instead of internal visibility?

Integration testing against the real CDN API revealed that posts with visibility: internal are completely hidden from all listing queries (by CDN plugin design), making it impossible to find and flip them later. The draft/publish approach works reliably and is idempotent — re-running when no drafts exist is a safe no-op.

Testing Instructions

  • Full end-to-end testing will happen during the next release cycle
  • The draft→publish flow was manually verified against the real CDN API

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

🤖 Generated with Claude Code

@iangmaia iangmaia changed the title Upload CDN builds as internal first, then publish as external [Tooling] Upload CDN builds as internal first, then publish as external Mar 3, 2026
@iangmaia iangmaia self-assigned this Mar 3, 2026
…ish_release

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@iangmaia iangmaia force-pushed the iangmaia/upload-cdn-builds-as-internal-first branch from e74bec3 to 921742d Compare March 3, 2026 12:41
@iangmaia iangmaia requested a review from Copilot March 3, 2026 12:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the release automation to upload Apps CDN artifacts as Internal first (for an internal testing window), and then flips them to External as part of publish_release before the GitHub release is published.

Changes:

  • Change Apps CDN uploads to use Internal visibility by default.
  • Add make_cdn_builds_public helper to find internal builds for a release version and update them to External visibility.
  • Update release lane prompts and call make_cdn_builds_public during publish_release.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

If publish_release is rerun after a partial failure, the builds may already
be external. Warn and continue instead of erroring out.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@iangmaia
Copy link
Contributor Author

iangmaia commented Mar 3, 2026

Converted to draft until the release-toolkit PRs aren't merged and we can use a new version with both actions.

@iangmaia iangmaia requested review from AliSoftware and mokagio March 3, 2026 18:47
… visibility

Upload release builds as external+draft, then publish them in publish_release.
The CDN plugin hides internal-visibility posts from all API queries,
making the previous internal→external approach unworkable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@iangmaia iangmaia changed the title [Tooling] Upload CDN builds as internal first, then publish as external [Tooling] Upload CDN builds as drafts, publish in publish_release Mar 4, 2026
@AliSoftware
Copy link
Contributor

Integration testing against the real CDN API revealed that posts with visibility: internal are completely hidden from all listing queries (by CDN plugin design), making it impossible to find and flip them later. The draft/publish approach works reliably and is idempotent — re-running when no drafts exist is a safe no-op.

What is the consequence of uploading a build to AppsCDN as "Draft", in terms of testability?
I'm guessing that just like a WP post, an app uploaded as "Draft" would not be visible when you load the WP site that lists the builds (just like draft posts aren't visible on a blog), so how would a Release Manager or the team be able to download and test the build in practice?

Maybe it'd be better to adjust the CDN plugin design to allow list_apps_cdn_builds to return internal builds somehow… though I guess it'd only allow listing internal builds if the call is done from a proxied IP, while CI machines (where those lanes run) are not proxied, so I guess that's the core of the problem… In that case I could think of 2 possible solutions:

  • Either use Draft status instead of visibility, like you did, but then ensuring it'd be possible (and easy) for the Release Manager to download the build for testing
  • Or store the post_id of the build that is uploaded as draft — but the question is where… maybe as some <!-- post_id:… --> hidden metadata in the GitHub Release draft description? Or as an annotation to the Buildkite build? — so you wouldn't have to use list_apps_cdn_builds to retrieve it later.

install_type: build[:install_type],
visibility: 'external',
visibility: :external,
post_status: release_tag&.match?(/beta/i) ? nil : 'draft',
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure the condition is right here?

This means that the first beta post code freeze as well as the intermediate betas that occur in the middle of the release will be uploaded as draft (and then never published). While those should probably be internal instead.

That also means that the final build we do at the end of the release process, the one that drops the beta suffix because it's supposed to be the final version, will not match the /beta/i RegEx, and thus will be uploaded as non-draft. While it's exactly not what we want.

Also, based on the code at the start of this lane, there also exists "Nightly Builds"—for which release_tag is nil, which means means this will publish those as non-draft as well.


I think instead we should:

  • For build_type of both Nightly and Beta, use visibility: :internal but post_status: 'publish', so that they are published but only internally
  • For build_type == 'Production builds, especially the final build done at the end of the release scenario, use visibility: :external but post_status: 'draft'… until we get to the next stage in the Release Scenario to publish it once it has been smoke-tested.

Comment on lines +310 to +311
# Update CDN build visibility from Internal to External
make_cdn_builds_public(version: version)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not consistent with what it currently does, which is not about making it public and changing it from internal to external, but about changing it from draft to published…

Of course this might change back depending of if using the Draft state was indeed the right move (i.e. if it still allows this build to be easily downloadable and testable by the team and RM for smoke-testing) or if we're gonna switch back to using internal vs external.

Comment on lines +836 to +841
release_version = "v#{version}"
builds = list_apps_cdn_builds(
site_id: WPCOM_STUDIO_SITE_ID,
version: release_version,
post_status: 'draft'
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a risk—especially in the rare case that issues was found in a final release build and the team decides to make a new commit on the release/ branch then re-upload a new final build—that there would be more than one build with version v#{version} in the CDN for each platform, and that we'd then end up publishing all of them (the bad one as well as the subsequent one with the fix) instead of only the last one?

Tbh I'm not sure this is a case the current setup fully support yet anyway.

  • e.g. what happens to the version bump logic if you finalize_release once, which removes the -betaN suffix from the version, then find an issue and redo another finalize_release, would the logic that removes the -betaN be a no-op on the version already being X.Y.Z? Will it crash?
  • What about the AppsCDN side of things, is the CDN plugin ok with uploading a build with the same metadata (version, platform…) twice? Does it replace the old one with the new one in that case, or keep both entries (which is where your list_apps_cdn_builds call would return duplicates)

Maybe it's only a concern for a future iteration though. But I figured I'd still raise the question, including in case this informs our thoughts about using visibility: :internal and not using list_apps_cdn_builds but storing the post_id values at initial upload time somewhere instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants