Skip to content

Work Items

Wes Key edited this page Sep 14, 2026 · 2 revisions

tf-snag can raise an Azure Boards work item for each finding, and keep it up to date as the finding is ignored, reinstated or fixed.

export TF_SNAG_ADO_TOKEN=...   # PAT or System.AccessToken
tf-snag -check all -plan plan.json -plan-log plan.jsonl -baseline prev.sarif \
  -ado-url https://dev.azure.com/my-org/my-project -ado-type Task -run-url "$RUN_URL"

In a pipeline, set the tf-snag@0 task's workItems input to dry-run, then on. Start with a dry run: -ado-dry-run (or workItems: dry-run) reports what would be raised and closed, and checks the token and permissions, without changing anything.

An Azure Boards task raised by tf-snag for a drifted key vault, tagged tf-snag, tf-snag-id and tf-snag-ignored, with Update and No longer ignored badges and a table of the changed tags attribute

A work item raised by tf-snag. The tf-snag-id-… tag ties it to exactly one finding, and the description carries the drifted attributes, the finding's badges and a link back to the run.

One finding, one work item

Every item tf-snag creates is tagged tf-snag and tf-snag-id-<finding id>, using the finding's stable id. Each run queries those tags, so Azure DevOps itself is the record of what has been raised, not a build artifact that can expire. The id comes from the resource address alone, so a finding keeps its item as the drifted values change.

While an item for a finding is open, every run links to it and none raises a second, wherever it has been moved on the board. Reports carry the link (work_item and work_item_url in JSON), and the run tab shows it on the finding.

If a finding already has more than one open item, tf-snag tracks the oldest, names the others in the run output, and changes none of them. Which to keep is a decision for a person.

What gets raised

-ado-raise Raises for
new (default) findings absent from -baseline, so adopting tf-snag against an estate full of drift does not open fifty items on day one
findings anything not ignored

An ignored finding never gets a new item: somebody has already decided not to act on it.

When a finding is ignored

Ignoring a finding does not close its item. Closing would tell the board the work was done when nobody did any, and the item may already be triaged or in a sprint. tf-snag comments once instead, saying the drift is still there and is no longer reported, and tags the item tf-snag-ignored so the comment is not repeated. Whether to close it is left to a person.

Removing the ignore rule resumes on the same item. The comment is retracted, the tag removed, and the finding is badged No longer ignored. No second item is raised.

When a finding goes away

With -ado-close, an item whose finding is no longer reported moves to -ado-closed-state, with a comment saying why. The state defaults to the work item type's own Completed state: Closed on Agile, Done on Scrum and Basic. A state you supply is checked against the type's real states before anything is closed.

Closing
CLI off by default. Pass -ado-close
tf-snag@0 task on by default (adoClose)

Closing is opt-in on the CLI because raising items only adds, while closing changes work someone may have triaged or linked.

A closed item is history, not a slot to reuse. If fixed drift comes back, it is a new occurrence and gets a new item, which opens with a comment naming the closed one it follows. Any state the process counts as Completed or Removed counts as closed.

Permissions

The token needs Work Items (Read & Write). Read is needed too, because finding existing items is a query.

Before changing anything, tf-snag makes a validate-only create. A bad token, project or work item type fails straight away, naming the problem, rather than halfway through a run. Azure DevOps answers an unauthenticated call with a sign-in page rather than a 401, and tf-snag reports that as "not authenticated".

-ado-token accepts a PAT or a pipeline's System.AccessToken; the type is detected from the token. Pass it through TF_SNAG_ADO_TOKEN rather than the command line. With System.AccessToken, the <Project> Build Service identity needs Edit work items in this node on the area path.

All work item output goes to stderr, so it never mixes into a report on stdout.

Clone this wiki locally