Beta build is blocked by the sample email templates

Open
#217 4 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Quiet

Research direction

Read cumulusci.yml and sfdx-project.json alongside the ancestry documentation; start by reviewing the package configuration and the evidence from PRs #215 and #216. Confirm the selected package strategy and separate source changes from Dev Hub and subscriber migration work. Done means the team has chosen a direction and the required build and migration steps are tracked.

Written by the indexing model from the issue text.

Description

BLOCKER

Summary

The beta build is currently broken. The cause is the three sample email
templates. Testing shows that no arrangement of these templates inside the
current package can both build and install. The suggested fix is to start a new
package in the same namespace, drop the sample templates from the managed
package, and deliver them a different way. Pilot users would reinstall once. This
note asks the team to choose a direction.

What is broken

  • When the templates are missing from the code, the build fails. Salesforce
    says EmailTemplate can't be removed.
  • When the templates are present, the build passes but the install fails. The
    install says the template is located in both the package and the unfiled-public folder.

Once a managed package ships an email template, it cannot be removed later. It
also cannot live in the shared "unfiled public" folder, which is where the
released version keeps them.

Why all four arrangements fail

The current package has four possible template arrangements. All four were
tested:

Templates in the code Build Install
None Fails (can't remove) n/a
In the shared public folder Passes Fails (collision)
In a named folder only Fails (can't remove the public ones) n/a
Both Passes Fails (collision)

The current package cannot produce a version that both builds and installs.
Pilot users who already installed keep working, but we cannot ship a new version
to them or to anyone new.

What this means for users

The app is still in pilot. It has not passed Security Review (issue #138), so it
is not on the AppExchange yet. The public still uses the old version 3 app. We do
not have an exact count of pilot installs. Now is the cheapest time to make this
change, before the public launch.

Options

Option Builds and installs? Effect on pilot users Main risk
Keep trying to fix the current package No. Tested, does not work. None Stays broken
Change the test setup to skip the templates No. Real installs still fail. None Green build that hides a broken install
New package, same namespace, templates delivered outside the package Yes Reinstall once, short link downtime Reinstall must be run per org
Brand new package and new namespace Yes Reinstall once, old unsubscribe links break Most rework, links break

Recommendation

Start a new package in the same namespace. A new package means a new package id
and a fresh version history, with none of the shipped templates locked into it.
Take the three sample templates out of the managed package. Deliver them as
unpackaged metadata in a separate optional step during installation, so admins
can edit or remove them freely.

  • A fresh package has no history to conflict with, so the build and install both
    pass. This is the only tested path that produces a working install.
  • Keeping the same namespace means every field keeps its name. The unsubscribe
    links already sent to people can keep working after the switch.
  • The templates were always samples. Delivering them outside the package keeps
    this problem from coming back. Admins can change or delete them anytime.

What it costs pilot users:

  • Each pilot org uninstalls the old version and installs the new one. There is no
    in-place upgrade between two separate packages.
  • During the switch there is a short window where the unsubscribe links do not
    work, because the old version is gone and the new one is not in yet.
  • We keep the opt-out records and the link values. Some system fields, like
    original created dates and field history, reset.
  • Not tested: the unsubscribe web page is set up inside each org and is not part
    of the package. If it does not survive the uninstall and reinstall, the links
    break and the org admin must set the page up again.

Also valid: reuse the current package, but build the next version with no
ancestor so the build stops comparing against the released 0.3.0.2 and no
longer tries to remove the templates. This keeps the current package id. The
trade-off is that a version built with no ancestor cannot be upgraded to from the
released versions, and it leaves a broken upgrade history on that package id that
can fail later builds. A fresh package starts clean and avoids that. Same
one-time reinstall for pilot users either way. See the ancestry doc.

Suggested next step

The team chooses a direction: new package (recommended), reuse the current
package with no ancestor, or something else. If the team chooses the new package,
the work splits into two parts:

  1. Source change (a normal pull request, no Dev Hub access needed): rename the
    package in cumulusci.yml (project.package.name) and in sfdx-project.json
    (the package name and the stale packageAliases), and add the three sample
    templates back as unpackaged metadata for delivery at install time.
  2. Dev Hub and subscriber-org actions (needs Dev Hub access, so RelEng
    completes): promote the release and run the per-org migration.

Technical details and evidence

Note on terms: "new package" below means a new Package2 (0Ho...) in the same
namespace. Same namespace with a new package is a supported 2GP shape.

The block
  • Package: 0Ho6g000000KzbvCAC, namespace UnsubscribeLnk, Dev Hub
    00D6g000007zf5wEAA (OSC-devhub).
  • Released chain is linear: 0.1.0.8 -> 0.2.0.6 -> 0.3.0.2. When
    create_package_version builds a new version, it compares the source against
    the highest promoted version and flags anything present there but missing now
    as a removed component. 0.3.0.2 (04tKf0000011MN6IAM) is the highest
    promoted version and it carries the three templates in unfiled$public. So a
    build with the templates absent diffs against 0.3.0.2, sees them as removed,
    and fails.
  • Setting 0.2.0.6 (the last template-free release) as the ancestor does not
    avoid this. A normal build must use the highest promoted version as its
    ancestor; the CLI rejects an older ancestor unless you pass
    --skip-ancestor-check. Skipping the check to build against 0.2.0.6, or
    building with no ancestor, is the reuse option in the recommendation: create
    passes, but the upgrade path from the released versions breaks.
  • EmailTemplate is not in the removable-component list for 2GP. The Dev Hub
    RemoveManagedComponentsAllowed flag does not unlock it; that flag only covers
    the listed types, and access still needs a Salesforce Partner Support case. See
    the removable components list.
  • The baseline keeps the templates in unfiled$public, not a named folder.
    Proof: PR #215 build (run 31140511460) failed at create_package_version and
    listed the removed components as unfiled$public/Sample_Contact_Template_HTML,
    unfiled$public/Sample_Lead_Template_HTML,
    unfiled$public/Sample_Lead_Template_Plain_Text.
  • PR #216 build (run 31193777829) shipped both the named folder and the
    unfiled$public copies. Package creation passed. Beta install failed with the
    both-locations collision.
  • The collision is between the packaged EmailTemplate and the org-owned
    unfiled$public EmailFolder, not a pre-existing same-named template. Every
    org has an unfiled$public EmailFolder, so a packaged EmailTemplate that
    targets it collides on every install. Test: installed beta 0.4.0.6
    (04tKf000000kjbCIAQ) into a fresh scratch org with zero pre-existing Sample
    templates and nothing in unfiled-public. Install failed with
    EmailTemplate Sample Lead Template file is located in both the package you tried to install, and in either the unfiled-public folder or a user folder. A
    2GP package cannot deliver an EmailTemplate into unfiled$public.
The new package is feasible with current tooling
  • Two 2GP packages can share one namespace in the same Dev Hub. See the
    1GP vs 2GP comparison.
  • CumulusCI's create_package_version resolves the package by name and namespace
    from cumulusci.yml (project.package.name + project.package.namespace),
    not by an id in sfdx-project.json. If no Package2 matches, it creates one
    using the DEV_HUB_AUTH_URL credentials. So renaming project.package.name
    makes the next beta build stand up the new package unattended, provided the CI
    identity has the "Create and Update Second-Generation Packages" permission it
    already uses to build versions today. If it lacks package-create rights,
    someone with Dev Hub access runs sf package create once by hand.
  • No GitHub workflow file needs a change. beta.yml, prod.yml, and
    feature.yml call the shared standard-workflows workflows and never pass a
    package id. DEV_HUB_AUTH_URL does not change, because both packages live in
    the same Dev Hub.
  • Manual Dev Hub equivalent, run by someone with Dev Hub access:
    sf package create --name "<new-name>" --package-type Managed --path force-app --target-dev-hub OSC-devhub, then sf package version create, then
    sf package version promote.
Who runs each step
  • Source edits (rename package in cumulusci.yml + sfdx-project.json, add the
    templates as unpackaged metadata): a pull request. Any contributor. No Dev Hub
    access needed.
  • New Package2 create: automatic on the first beta build via CI, or a one-time
    sf package create by someone with Dev Hub access if CI lacks the permission.
  • CI beta build: unattended, on merge to main.
  • Version promote (release): needs Dev Hub access. Deliberate and irreversible.
  • Subscriber migration: hand-held per pilot org, needs subscriber-org admin
    access. There is no License Management App, so we cannot list installs
    automatically. Each org needs direct outreach and a maintenance window.
Migration mechanics and limits
  • No overlap window. Same namespace plus same field API names means an org cannot
    hold both packages at once, so the sequence is: export data, uninstall old,
    install new, re-import. Two package versions can upgrade in place only if they
    share an ancestry path, which two separate packages never do. See the
    upgrade/ancestry doc.
  • The uninstall and install steps are manual admin actions (Setup UI or
    sf package uninstall/install). Only the data export and re-import can be
    scripted. How to run those is the team's choice, based on how many pilot orgs
    there are and the owner's bandwidth:
    • Automate as a CumulusCI flow: extract_dataset before uninstall,
      load_dataset after install, matching on the external id. Repeatable per org.
    • Wrap it as a MetaDeploy plan for a guided, admin-run migration.
    • For a few orgs, run the export and re-import by hand with Data Loader instead
      of automating.
  • Data surface: Unsubscribe__c records (opt-out data, must be preserved),
    Contact.Public_Id__c (unique external id, backs live unsubscribe URLs, must
    be preserved), Contact.Part1_Unsubscribe_Link__c (flow-populated), and the
    Lead equivalents. Unsubscribe_Link_Setup__c is a custom setting
    (re-enterable). Two formula fields carry no stored data.
  • Preserve Public_Id__c by upsert on the external id field
    (CumulusCI load_dataset or Data Loader), not plain insert. Lost on uninstall
    and not restorable: original record ids, created/modified dates, field history.
  • Largest untested risk: the unsubscribe URL routes through an
    Experience/Digital Experience site that each subscriber sets up. It is not a
    package component. Whether its page references survive an uninstall then
    reinstall is not confirmed. Confirm this in a test org before committing pilot
    users.
Dominant language
Apex
Stars
9
Forks
22
Avg merge
2d 22h
Merged PRs (30d)
3

Getting set up

  • No Dockerfile or Docker Compose file
  • Has a pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from SFDO-Community/UnsubscribeLink

All issues in SFDO-Community/UnsubscribeLink

Similar issues

More Build System issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.