Koppel-plugin publiceren (Partner Center-submit)

Dit is het interne runbook voor het uitbrengen van een nieuwe versie van de Koppel Outlook-plugin, van platformrelease tot de handmatige submissie in Microsoft Partner Center. Het hoort bij spoor 9 van Koppel 2.0 (#3119).

Voorwaarde: er ligt een GitHub-release uit de pipeline. De enige geldige route naar Partner Center loopt via de release-workflow (.github/workflows/koppel-release.yml). Wie met de hand een manifest bewerkt en dat uploadt, omzeilt alle guards (GUID-check, dev-URL-check, versiecheck, bereikbaarheidscheck) en herhaalt vroeg of laat de fouten die deze pipeline juist moet uitsluiten.

Waarom de laatste stap handwerk is

Onderzocht in #3118: er bestaat geen API om een Office add-in automatisch in te dienen.

  • Office add-ins zijn expliciet uitgesloten van de Partner Center submission API’s.
  • De nieuwere Product Ingestion API werkt alleen met offer type “Apps and agents for Microsoft 365 and Copilot” (unified manifest) en is public preview.
  • Migreren naar de unified manifest zou die API ontsluiten, maar kost ondersteuning op perpetual Office, Outlook voor Mac en mobiel. Dat is een losse afweging, geen CI-kwestie.

Alles tot aan de submit is dus geautomatiseerd; de upload zelf blijft een handmatige actie in Partner Center. Zoek dit niet opnieuw uit voordat de situatie bij Microsoft aantoonbaar veranderd is.

Wat nooit mag wijzigen: de GUID

De <Id> van het productiemanifest is en blijft 22bfb058-fa04-4d59-9279-df7ee1c41c82 (dev: 83069ba7-80d4-4179-a47f-87f0b9da6165). Wijzigt de <Id>, dan ziet Partner Center het bestand als een NIEUWE app in plaats van een update van de bestaande, met alle gevolgen voor bestaande installaties. Guard 1 in tools/koppel-manifest/src/check.ts blokkeert elke afwijking; de constante in dat script is de bron van waarheid.

De versie volgt de platformrelease (gekozen in #3139)

Handmatig bumpen en handmatig taggen zijn vervallen. De Koppel-versie loopt gelijk met de platformversie van release-please: platformtag v15.111.0 wordt manifestversie 15.111.0.0 met release-tag koppel-v15.111.0 (het vierde manifestveld is altijd 0).

De release-workflow (koppel-release.yml) draait bij elke platformtag, maar releaset alleen als het productiemanifest inhoudelijk gewijzigd is sinds de laatste koppel-v*-tag. Die vergelijking negeert het <Version>-element (anders zou de terugcommit van de vorige release elke platformrelease opnieuw laten releasen). Geen inhoudelijke wijziging: de workflow stopt netjes, zonder release en zonder commit. Is er nog geen koppel-v*-tag, dan geldt dat als eerste release.

Bij een echte wijziging zet de workflow de versie, draait hij validatie plus alle guards (strikte versiecheck tegen de vorige koppel-v*-tag), commit hij de gebumpte manifests met [skip ci] terug naar main en zet hij de koppel-v*-tag op precies die commit. De release-asset staat zo byte-voor-byte gelijk aan wat er op main staat. De koppel-v*-tags blijven dus bestaan als registratie van wat er daadwerkelijk gereleased is; ze worden alleen niet meer handmatig gezet.

Let op de versiesprong: de eerste automatische release springt van 1.3.1.0 naar 15.x.y.0. Partner Center eist alleen “hoger dan de vorige versie”, dus dat kan. Is de herindiening met 1.3.1.0 (#3078) nog gewenst, doe die dan vóór de eerste automatische release; daarna is 1.3.1.0 voorgoed te laag.

De testinstructies voor de reviewer horen bij elke submissie

Naast het manifest gaat er bij elke indiening een document met testinstructies mee naar de Microsoft-certificeringsploeg. De bron daarvan staat in de repo: tools/koppel-test-instructions/src/test-instructions.md. De release-pipeline bouwt daar bij elke Koppel-release een PDF van en hangt die als tweede release-asset naast het manifest.

Drie dingen om te weten:

  • Het document houdt zijn eigen versieteller (1.7, 1.8, 1.9), los van de manifestversie en de koppel-v*-tag. De reviewer volgt “seventh resubmission” als continuïteit tussen reviewrondes, en die betekenis verdwijnt zodra het nummer naar 15.111.0 springt. De manifestversie en de tag komen alleen als stempel op de titelpagina, zodat duidelijk is bij welk pakket de instructies horen.
  • De guards bewaken versheid en samenhang, niet de inhoud. Ze controleren of de revisiehistorie bij de versie past, of de versie omhoog ging toen de tekst veranderde, of er geen placeholders zijn blijven staan, of de testgegevens niet verjaard zijn, of elk oppervlak uit het productiemanifest een scenario heeft, en of alle links reageren. Wat er in een revisie staat is mensenwerk: dat is de reactie op een concrete afwijzing.
  • Het wachtwoord van het Exact-testaccount staat niet in git. In de bron staat ``; de build vult dat in uit het repository-secret met dezelfde naam en faalt hard als het secret ontbreekt. Zet het wachtwoord dus nooit in deze docs/-map: die wordt publiek gepubliceerd op docs.tapster.nl.

Verjaringsguard. Guard 4 laat de release falen zodra credentials_verified_on in de frontmatter ouder is dan 30 dagen. Het document belooft letterlijk “credentials verified current on "; die belofte moet waar zijn op het moment van indienen. De fix is altijd dezelfde: log in op het Exact-testaccount, controleer dat het werkt, en werk het veld bij in een PR. Op PR's is dezelfde guard een waarschuwing, zodat een PR niet rood wordt omdat er die maand niet is ingelogd.

Stap voor stap

  1. Merge de manifestwijziging naar main via een gewone PR. De workflow koppel-validate.yml draait de manifestvalidatie en de guards al op de PR. Bump de versie niet zelf; dat doet de release-workflow.

  2. Wacht op de eerstvolgende platformrelease (release-please-tag v15.x.y). De workflow Koppel plugin release in de Actions-tab ziet de manifestwijziging, bumpt en tagt, maakt een GitHub-release met outlook-manifest-production.xml als asset en opent een issue met het label koppel-release als melding. Faalt een guard, dan komt er geen release; fix de oorzaak en wacht op de volgende platformrelease (of her-run de workflow op de tag).

  3. Download de assets van de release-pagina: outlook-manifest-production.xml én Koppel_AppSource_Test_Instructions_v<versie>.pdf. Upload precies deze bestanden; bewerk ze niet. De PDF wordt vlak na het aanmaken van de release aangehangen door de job testinstructies; staat hij er niet, kijk dan in de Actions-tab waarom die job faalde en her-run hem.

  4. Dien in bij Partner Center:
    1. Ga naar Partner Center en open onder Marketplace offers de bestaande Koppel Office add-in.
    2. Start een nieuwe submissie (update van de bestaande listing; maak nooit een nieuw offer aan).
    3. Upload de gedownloade outlook-manifest-production.xml als het add-in-pakket. Een Office add-in wordt als los XML-bestand ingediend, niet als zip.
    4. Upload de PDF met testinstructies bij de certification notes / supplemental content van de submissie.
    5. Vul de certification notes in. Type de nuances niet opnieuw over: verwijs naar het meegeleverde document. De gedeelde-mailbox-scope uit #3078 staat in §6.6 en §8 van dat document: het manifest zet SupportsSharedFolders (in VersionOverridesV1_1; een eerdere afwijzing kwam door een schema-invalide plaatsing in V1_0), en de agenda-surfaces (AppointmentOrganizerCommandSurface en AppointmentAttendeeCommandSurface) dragen de eigen-agenda-functionaliteit, terwijl gedeelde agenda’s beperkter ondersteund zijn. Guard 5 bewaakt dat elk oppervlak uit het manifest daadwerkelijk een scenario in het document heeft, dus wat je hier belooft staat er ook echt in.
    6. Rond de submissie af en wacht de validatie van Microsoft af (dagen, geen uren).
  5. Sluit het koppel-release-issue met een comment over de uitkomst van de submissie. Dat issue is het spoor van welk manifest wanneer is ingediend.

Wat te doen bij een afwijzing

  • “Version already exists” of een identieke versie. Dit is precies wat er bij 1.3.0.0 gebeurde: beide manifests stonden op dezelfde versie als de live listing en de submissie werd afgewezen. Guard 3 hoort dit nu voor de release te vangen (de versie moet strikt hoger zijn dan de laatste koppel-v*-tag). Gebeurt het toch: wacht op de volgende platformrelease (die levert vanzelf een hogere versie) en doorloop het runbook opnieuw.
  • Inhoudelijke afwijzing (gedrag, screenshots, certification notes): fix de oorzaak, en als het manifest wijzigt, altijd via een nieuwe tag en release. Nooit het gedownloade bestand met de hand aanpassen en opnieuw uploaden.
  • Werk de testinstructies bij vóór je opnieuw indient. Elke afwijzing tot nu toe heeft een revisie aan het document toegevoegd; dat is precies de continuïteit die de reviewer volgt. De volgorde is:
    1. Open een PR die tools/koppel-test-instructions/src/test-instructions.md aanpast: verhoog version in de frontmatter (1.71.8), zet submission op de volgende ronde, en voeg bovenaan §1 een revisie-entry toe die beschrijft wat er op de afwijzing is gedaan. Is er inmiddels opnieuw ingelogd op het Exact-testaccount, werk dan ook credentials_verified_on bij.
    2. koppel-validate.yml draait de guards en een testbuild op die PR. Guard 1 valt over een bump zonder revisietekst, guard 2 over gewijzigde tekst zonder bump.
    3. Merge, en doorloop daarna pas het runbook opnieuw voor een nieuwe release.
  • Twijfel over de oorzaak: vergelijk de asset uit de release met wat er is geüpload; die moeten byte-voor-byte gelijk zijn.

Valkuilen uit eerdere sporen

  • Twee manifests met dezelfde versienaam. Er hebben in AppSource al eens twee pakketten onder versienaam 1.3.0.0 bestaan; dat maakte onduidelijk welk bestand live stond en leidde tot de handmatige bump naar 1.3.1.0. Sinds set-version komt de versie uit de tag en zijn beide manifests altijd gelijk.
  • De GUID wijzigen “om iets te testen”. Nooit doen in het productiemanifest; gebruik daarvoor het dev-manifest, dat een eigen GUID heeft.
  • De dev-URL-guard geldt alleen voor productie. Het dev-manifest wijst legitiem naar apiv7.dev.tapster.nl; alleen het productiemanifest mag geen localhost, 127.0.0.1 of .dev.tapster.nl bevatten.