Skip to content

A practical CI gate for classic Exstream packages

Classic Exstream Design and Production release pipelines using compiled PUB packages · Published 2026-08-21

By Tomas Hajek, working with Exstream since 2008

The Design repository owns versions and approval. A PUB file is a compiled deployment artifact. A pipeline that only copies packages cannot apply ordinary source-code assumptions to either one.

A useful CI gate respects those boundaries. It makes the artifact inspectable, compares it with an approved baseline, and gives a reviewer evidence they can understand.

Decide what the gate protects

There are several legitimate comparisons:

  • The new PUB against the previously deployed PUB.
  • The package about to deploy against the approved repository state.
  • The approved repository state against an earlier approved version.
  • The latest working state against approved, for pre-approval review.

Do not combine these into one unexplained "diff" step. Name both inputs and the reason they should agree or differ.

For a normal deployment, I would keep two checks: new package versus deployed package, and new package versus approved repository state.

Make artifact identity non-negotiable

Hash the exact PUB entering the pipeline. Record the application identity, package creation date, Design Manager version, package approval selection, and tool version that generated the report.

The approval record should point to the digest. A filename such as CustomerLetters_Final_2.pub is not provenance.

Produce a structured state

Generate a detailed design-state document from the new package:

exstream-package-cli state CustomerLetters.pub \
  --depth detailed --out package-state.json

Generate the approved repository state through a read-only profile:

exstream-design-cli app state "Customer Letters" \
  --profile release --mode approved --depth detailed --json \
  > approved-state.json

Validate both documents against the published schemas if another pipeline component consumes them. The schema version and document kind travel inside the files, so an old consumer can refuse a contract it does not understand.

Gate on a semantic diff

For the package-to-package check:

exstream-package-cli diff deployed.pub CustomerLetters.pub \
  --json-mode detailed --fail-on-change \
  --format html --out package-diff.html

For the repository-to-package check:

exstream-package-cli diff approved-state.json CustomerLetters.pub \
  --lineage same-lineage \
  --population intersecting-populations \
  --json-mode detailed --fail-on-change \
  --format html --out repository-package-diff.html

The package CLI returns a distinct exit code when the gate matches. The report is still produced, so the pipeline can publish it as a review artifact rather than replacing the explanation with a red status icon.

Write the policy before enabling the failure

Not every difference should block every environment.

A development pipeline may accept differences and publish the review. A test promotion may require an approved reviewer for changes to wording, formulas, rules, mappings, and output configuration. A production promotion may require the package to match the approved repository state and the expected change set.

Coverage needs policy too. A package comparison that found no differences among comparable fields is not the same as full agreement if some fields were unavailable. Decide which unavailable paths are acceptable for each package generation and which require manual review.

Do not invent a percentage such as 95 and call it safe. Look at which fields make up the missing 5 percent.

Give reviewers a usable artifact

Raw JSON is for machines. The release reviewer needs the verdict, coverage, affected objects, and the change itself.

Publish a self-contained HTML or Markdown review that groups findings by document and section. Show an edited sentence as an edited sentence, a formula change as a code diff, and a moved data mapping as a mapping change.

Keep detailed reports inside the same access boundary as the design. They may contain correspondence wording, business rules, data paths, and customer-specific names.

Add output regression beside it

The semantic gate does not render documents. Keep representative engine runs and output comparisons in the release pipeline.

The two controls catch different failures:

  • Design-state comparison catches unexpected source, mapping, setting, and wording changes even when the test data never reaches them.
  • Output regression catches engine, driver, font, resource, sorting, accessibility, and rendering changes that the design state cannot predict.

Store both results in the release record because they cover different failures.

Roll it out without drowning the team

Start in report-only mode on several real releases. Review the noise, package generations, unavailable fields, and legitimate recurring changes. Then enable failures on a narrow set of clearly unwanted outcomes.

A CI gate earns trust when its red builds mean something. If the team learns to rerun or override it by habit, the control is already gone.

CCMForge Inspect produces the structured states, package and repository diffs, review pages, schemas, and exit codes used in this release pattern.

Read the repository or package as structured data.

Inspect inventories the Design repository and compiled PUB package, extracts supported content, and compares any two states. Start with a free package overview or discuss a repository inventory.

These articles describe field experience and identify the Exstream versions they cover. They are not official vendor guidance. CCMForge is independent and is not affiliated with or endorsed by OpenText. OpenText and Exstream are trademarks of their respective owner.