Bean & Bark: ship Roastery Desk

View .md

The Orders API is live and the Pricing SDK is shared, but the physical roastery still runs on spreadsheets. Nadia wants Roastery Desk for batch intake, labels, and stock counts. Her MacBook is on the tasting floor, Tunde has a Windows laptop, and the packing station runs Linux. A publish folder on your machine is not a release any of them can install.

You'll learn
  • Declare one versioned desktop product across macOS, Windows, and Linux runtime identifiers
  • Create permission-safe first downloads and prove every routed cell without publication authority
  • Stage a feed-derived candidate for hands-on testing on all three operating systems
  • Promote the approved candidate byte-identically and understand the native-installer graduation path

Name the product version once

Distribution reads the product version from the project or nearest Directory.Build.props. Put it where code review can see it; a candidate will append a feed-derived -rc.N, while the stable release keeps the clean base.

xml
<PropertyGroup>  <Version>1.0.0</Version></PropertyGroup>

Turn a publish tree into three downloads

--scaffold-archive creates a small checked-in .NET helper and wires it into the manifest. Windows gets ZIP; macOS and Linux get permission-preserving TAR.GZ. The helper writes only declared archives into the output folder, so checksums and uploads do not accidentally include the loose publish tree.

bash
kanject add distributable src/BeanAndBark.RoasteryDesk/BeanAndBark.RoasteryDesk.csproj   --id roastery-desk   --rid osx-arm64   --rid win-x64   --rid linux-x64   --self-contained   --scaffold-archivekanject configure distribution   --env prod   --distributable roastery-desk

The guided distribution command records selector → destination rows in the prod stage. One wildcard can route every RID to the downloads bucket; exact RID rows can override it later without changing the application manifest.

Climb the safety ladder

Before AWS credentials enter the room, ask two progressively stronger questions: is the local plan coherent, and can the real artifact path finish?

bash
kanject doctor --features# Plan every cell without AWS or destination credentialskanject aws distribute   --env prod   --distributable roastery-desk   --dry-run --offline# Produce the real archives and checksums, but upload nothingkanject aws distribute   --env prod   --distributable roastery-desk   --no-publish

The offline plan prints all three cells and the source of 1.0.0. The build-only run publishes, archives, verifies, and checksums each cell under .kanject/dist/roastery-desk/..., but has no upload or ledger side effect. You unpack each archive and launch it on the matching machine.

bash
kanject aws distribute --env prod --distributable roastery-desk --rid osx-arm64 --no-publish

Confirm the arm64 archive launches and preserves executable permissions. A native DMG later adds .app identity, Developer ID signing, notarization, stapling, and Gatekeeper verification.

powershell
kanject aws distribute --env prod --distributable roastery-desk --rid win-x64 --no-publish

Confirm the self-contained ZIP launches without a preinstalled runtime. A native MSI later adds upgrade identity, shortcuts, WiX construction, and Authenticode verification.

bash
kanject aws distribute --env prod --distributable roastery-desk --rid linux-x64 --no-publish

Confirm the TAR.GZ preserves the executable bit. A native DEB later adds ownership, dependencies, desktop metadata, and package-manager inspection.

Stage one candidate for three people

distribute init creates or adopts the stable downloads bucket and its isolated -rc sibling, then enforces public-access block, encryption, and versioning. Candidate numbering comes from the candidate feed, so the pipeline cannot collide by guessing a suffix.

bash
# Create/adopt stable + candidate buckets and security posturekanject aws distribute init --env prod# Stage the next feed-derived 1.0.0-rc.N releasekanject aws distribute   --candidate   --env prod   --distributable roastery-desk# After the three-machine check, promote the exact candidatekanject aws distribute promote --env prod

Nadia, Tunde, and the packing operator download 1.0.0-rc.1 from the candidate channel. The approval records that all three cells passed hands-on checks. promote then performs server-side copies into stable destinations and flips the stable feed to 1.0.0; no compiler, archive helper, or signing script runs again.

When an archive is no longer enough

Saturday's internal pilot can use archives. A customer-facing release needs native identity and OS trust. Scaffold the inert release kit only after the archive path is green:

bash
kanject configure distribution scaffold   --distributable roastery-desk

The generated README and RID router carry runnable DMG, MSI, and DEB starters plus payload/container signing and independent verification. They are intentionally not activated for you: bundle identifiers, upgrade codes, entitlements, certificates, notarization credentials, install scope, and Linux metadata are product decisions.

Recap
  • A reviewed <Version> plus edition × RID manifest defines the product matrix; --scaffold-archive creates the first usable downloads.
  • Offline dry-run proves local intent, while --no-publish executes the real artifact path without destination authority.
  • The candidate feed owns -rc.N; people test those downloads on matching operating systems before approval.
  • promote copies the approved bytes to stable without rebuilding; native DMG/MSI/DEB graduation stays explicit and matching-OS.
Before Saturday's handoff2
Why can't candidate planning be fully offline?
What happens during stable promotion?
Try it yourself 2
1 Inspect the three local artifacts
Run --no-publish for a three-RID sample, unpack each archive, and compare executable permissions plus SHA256SUMS coverage.
The archive helper intentionally uses ZIP for Windows and TAR.GZ where Unix permission bits matter.
Show solution
The declared archive and checksum file should be the release surface; the loose publish directory should not appear in artifactGlobs or the upload set. Unix executables should retain their executable bits after extraction.
2 Explain the approval boundary
Write the shortest argument for why a release pipeline should promote an RC rather than rebuild stable installers.
Show solution
Approval refers to evidence about specific tested bytes. A rebuild creates different, untested bytes—even from the same commit—so stable promotion must preserve the candidate payload.
Was this page helpful?