Skip to content

Extend Remove-IshPublicationOutput with -Unrelease to support archiving of released publication outputs #268

Description

@ddemeyer

Business case

Large Tridion Docs repositories accumulate released publication outputs whose rendered blobs (PDF, HTML packages) are no longer needed. Because Remove-IshPublicationOutput cannot delete a VPUBSTATUSRELEASED output - the server rejects the deletion - a manual unrelease step is currently required before any removal. For bulk archiving operations over thousands of outputs this is a significant friction point.

Community thread: https://community.rws.com/product-groups/tridion/tridion-docs/f/forum/61643/shrinking-a-large-test-database-can-you-create-a-new-db-with-all-the-existing-metadata-but-no-data

Adding a -Unrelease switch to the existing Remove-IshPublicationOutput cmdlet covers this in a single pass with no new cmdlets, no new enumerations, and no extra server round-trips beyond the unrelease call itself.

Key design point: the version and logical metadata shells (title, baseline, context document) survive removal of a lng card automatically - the cascade that deletes version and logical cards is entirely client-side and is already controlled by the existing -Force switch. A caller who wants to preserve the shells for future republishing simply omits -Force and does not pipe the lng card they wish to keep. No additional protection logic is needed inside the cmdlet.

How to use

Typical archiving pattern - dry run first, then commit:

New-IshSession -WsBaseUrl "https://example.com/ISHWS/"
$oldFilter = Set-IshMetadataFilterField -Name "FISHLASTMODIFIEDON" -Level Lng `
    -ValueType Value -FilterOperator LessThan -Value "01/01/2022 00:00:00"

# Dry run - see what would be unreleased and removed
Get-IshFolder -FolderPath "General\MyPublications" -FolderTypeFilter @("ISHPublication") -Recurse |
    ForEach-Object -Process {
        Get-IshFolderContent -IshFolder $_ -VersionFilter "" -MetadataFilter $oldFilter |
            Remove-IshPublicationOutput -Unrelease -WhatIf
    }

# Commit - remove lng cards, version/logical shells survive (no -Force)
Get-IshFolder -FolderPath "General\MyPublications" -FolderTypeFilter @("ISHPublication") -Recurse |
    ForEach-Object -Process {
        Get-IshFolderContent -IshFolder $_ -VersionFilter "" -MetadataFilter $oldFilter |
            Remove-IshPublicationOutput -Unrelease
    }

# Full cleanup - remove lng cards and cascade-delete empty version/logical shells
Get-IshFolder -FolderPath "General\MyPublications" -FolderTypeFilter @("ISHPublication") -Recurse |
    ForEach-Object -Process {
        Get-IshFolderContent -IshFolder $_ -VersionFilter "" -MetadataFilter $oldFilter |
            Remove-IshPublicationOutput -Unrelease -Force
    }

Optional: download rendered blobs before removing (memory-safe, one folder at a time):

New-IshSession -WsBaseUrl "https://example.com/ISHWS/"
$oldFilter = Set-IshMetadataFilterField -Name "FISHLASTMODIFIEDON" -Level Lng `
    -ValueType Value -FilterOperator LessThan -Value "01/01/2022 00:00:00"
Get-IshFolder -FolderPath "General\MyPublications" -FolderTypeFilter @("ISHPublication") -Recurse |
    ForEach-Object -Process {
        Get-IshFolderContent -IshFolder $_ -VersionFilter "" -MetadataFilter $oldFilter |
            Tee-Object -Variable folderPublications |
            Get-IshPublicationOutputData -FolderPath "C:\Temp\Archive"
        $folderPublications | Remove-IshPublicationOutput -Unrelease
    }
# Note: Get-IshPublicationOutputData only downloads outputs that have rendered data.
# Draft-only outputs produce no file silently.
# Uncomment to push downloads to S3 (AWS.Tools.S3 required):
# Get-IshPublicationOutputData -FolderPath "C:\Temp\Archive" |
#     ForEach-Object { Write-S3Object -BucketName "my-docs-archive" -File $_.FullName -Key $_.Name }

Known limitations

  • Currently-publishing outputs are skipped: outputs in VPUBSTATUSPUBLISHING status emit a WriteWarning and are neither unreleased nor removed. Re-run after publishing completes.
  • Unrelease requires 14SP4 with CRQ-31475 hotfix, or 15.0.0+. On older servers the SetMetadataByIshLngRef unrelease call will throw. Without -Unrelease the existing behaviour is unchanged on all versions.
  • Database space recovery: requires time up to 24 hours because the Crawler services makes the marked-for-deletion of the PublicationOutput an actual delete. Then a InfoShareCM_StandardInfoShareJob run actually frees up the records of the Electronic Documents (ED), since 15.3.0 this is a synchronous action and no longer requires the database job. Last is the defragmentation or shrinking that needs to be handled by the database engine.
  • Caller controls which cards survive - to preserve version/logical metadata shells for future republishing, omit -Force and do not pipe the lng card you wish to keep. The version and logical shells are never auto-deleted by the server; cascade deletion is always client-side via -Force.

Tasks

Implementation

  • Add [SwitchParameter] Unrelease property to RemoveIshPublicationOutput.cs, both IshObjectGroup and ParameterGroup parameter sets, Mandatory = false; add <para type="description"> XML doc
  • In ProcessRecord, pipeline path (IshObject != null): before DeleteByIshLngRef, check FISHPUBSTATUS of the current lng card
    • Reuse FISHPUBSTATUS from ishObject.IshFields if the caller pre-fetched it; otherwise fall back to RetrieveMetadataByIshLngRefs for that single lngRef
    • If VPUBSTATUSPUBLISHING: WriteWarning + continue (skip both unrelease and delete)
    • If VPUBSTATUSRELEASED and Unrelease.IsPresent: ShouldProcess(lngRef + " Unrelease") + SetMetadataByIshLngRef with FISHPUBSTATUS = VPUBSTATUSPUBLISHINGCANCELLED
    • Proceed to DeleteByIshLngRef as today
  • In ProcessRecord, ParameterGroup path: same status check and conditional unrelease before Delete(LogicalId, Version, OutputFormat, LanguageCombination, ...)
  • -Force cascade logic (ProcessRecord:174-226): unchanged
  • -RequiredCurrentMetadata: unchanged, passed to delete as today
  • ShouldProcess target string for unrelease step distinguishable from delete step in -WhatIf output
  • Update triple-slash XML doc synopsis and description; add a new <example> showing the archiving pattern with -Unrelease and folder-walk

Testing

  • Extend RemoveIshPublicationOutput.Tests.ps1 with -Unrelease context
  • Test: -Unrelease on a draft-status output removed directly without unrelease call
  • Test: -Unrelease with -WhatIf - nothing changed, both unrelease and delete described in output
  • Test: -Unrelease -Force - lng removed, version and logical shells cascade-deleted when last lng
  • Note: full unrelease coverage (starting from VPUBSTATUSRELEASED) requires a prior publish cycle; deferred to manual testing as noted in existing test file

Documentation


Out of scope


Implementation notes

  • FISHPUBSTATUS check: reuse from ishObject.IshFields when present to avoid an extra server call; only call RetrieveMetadataByIshLngRefs when the field is absent on the incoming object
  • VPUBSTATUSPUBLISHING guard must precede both the unrelease attempt and the delete attempt - a currently-publishing output cannot be unreleased or deleted by the API
  • No new enum, no new cmdlet, no accumulation, no EndProcessing flush - throughput matches the existing cmdlet exactly plus one SetMetadataByIshLngRef per released card
  • VerbsCommon.Remove cmdlet stays as-is; only a new switch parameter and status-check block are added

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions