Skip to content

[IACP-673] Add terraform upload command for IaC artifact ingestion#2129

Merged
vishal-joshi-datadog merged 19 commits intomasterfrom
vj/IACP-673
Feb 27, 2026
Merged

[IACP-673] Add terraform upload command for IaC artifact ingestion#2129
vishal-joshi-datadog merged 19 commits intomasterfrom
vj/IACP-673

Conversation

@vishal-joshi-datadog
Copy link
Contributor

@vishal-joshi-datadog vishal-joshi-datadog commented Feb 25, 2026

Summary

Implements new datadog-ci terraform upload command to upload Terraform plan and state JSON files to Datadog CI intake API for enhanced cloud-to-code mapping and policy evaluation.

Changes

  • Base command structure: Added packages/base/src/commands/terraform/ with CLI registration and command options
  • Plugin implementation: Created packages/plugin-terraform/ with full upload logic
  • Architecture: Follows existing plugin patterns (similar to coverage, sbom plugins)
  • Multipart upload: Event envelope + gzipped IaC file to /api/v2/ciiac endpoint
  • Auto-enrichment: Git/CI metadata, SHA256 hashing, file size calculation
  • Features: Dry-run mode, verbose logging, optional repo-id override, retry logic

Usage

# Upload Terraform plan
datadog-ci terraform upload plan ./terraform-plan.json

# Upload Terraform state
datadog-ci terraform upload state ./terraform.tfstate

# With flags
datadog-ci terraform upload plan ./plan.json --repo-id "github.com/org/repo" --dry-run --verbose

Key Features

  • Single file per invocation (users can loop for multiple files)
  • No client-side validation/filtering (per RFC requirements)
  • Automatic git metadata sync (with skip option)
  • Supports all Datadog sites via DD_SITE environment variable
  • Gzip compression and SHA256 hashing
  • Retry logic for transient failures

Technical Details

  • Event envelope includes: artifact type, hash, size, git/CI context, repo_id
  • Uses multipart/form-data with event JSON + iac_file gzipped content
  • Integration with existing git-metadata upload helper
  • TypeScript build and linting passing

Testing

  • TypeScript build passes
  • Linting passes
  • Unit tests
  • Integration tests

Documentation

  • Plugin README: packages/plugin-terraform/README.md
  • JIRA
  • RFC

🤖 Generated with Claude Code

Implements new `datadog-ci terraform upload` command to upload Terraform
plan and state JSON files to Datadog CI intake API.

Key features:
- Upload Terraform plan or state files to /api/v2/ciiac endpoint
- Automatic git/CI metadata enrichment
- SHA256 hashing and gzip compression of artifacts
- Retry logic for transient failures
- Dry-run and verbose modes
- Optional repo-id override

Architecture:
- Base command in packages/base/src/commands/terraform/
- Plugin implementation in packages/plugin-terraform/
- Follows existing plugin architecture patterns (similar to coverage, sbom)
- Multipart/form-data upload with event envelope + gzipped file

Technical details:
- Single file per invocation (users can loop for multiple files)
- No client-side validation/filtering (per RFC requirements)
- Event envelope includes artifact type, hash, size, and git/CI context
- Supports all Datadog sites via DD_SITE environment variable

Implementation plan: tf_command_plan.md
RFC: /Users/vishal.joshi/Downloads/iac_artifact_rfc.md
@vishal-joshi-datadog vishal-joshi-datadog requested review from a team as code owners February 25, 2026 19:11
@datadog-datadog-prod-us1
Copy link

datadog-datadog-prod-us1 bot commented Feb 25, 2026

✅ Tests

🎉 All green!

❄️ No new flaky tests detected
🧪 All tests passed

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 62496c3 | Docs | Datadog PR Page | Was this helpful? React with 👍/👎 or give us feedback!

Copy link
Contributor

@rtrieu rtrieu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor suggestion


## Development

When developing software, you can try with the following command:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When developing software, you can try with the following command:
To test locally, run:

- Add api.test.ts with 7 tests covering multipart upload, gzip compression, and event envelope structure
- Add utils.test.ts with 28 tests covering validation functions, hash computation, and repo ID resolution
- Add upload.test.ts with 8 tests covering command execution, validation, and error handling
- Add test fixtures for valid plan, valid state, and invalid JSON files
- Mock git-related functions to prevent test timeouts

All 43 tests passing
@vishal-joshi-datadog vishal-joshi-datadog added the datadog-ci For PRs spanning multiple commands, and repo-wide changes label Feb 25, 2026
- Replace path with upath for Windows compatibility
- Remove unused fs import
- Add upath as devDependency
- Add --fips and --fips-ignore-error flags to base command
- Import and call enableFips in plugin implementation
- Add FIPS config from environment variables
- Add terraform upload to required options in CLI tests
- Add beforeEach to clear mock between tests
- All FIPS tests passing ✓
Copy link
Contributor

@ava-silver ava-silver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall lgtm, just a couple nits before I approve

Comment on lines +26 to +27
// Artifact type: 'plan' or 'state'
protected artifactType = Option.String({required: true})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can make validation (and typing!) easier by using typanion for validation, for example, isEnum can be used for enums here. An example of usage in this repo:

public action = Option.String({validator: t.isEnum(['disable', 'enable'] as const)})

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

import chalk from 'chalk'

import {TerraformArtifactPayload} from './interfaces'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mind at least using these constants in your renderers to keep the style consistent?

export const dryRunTag = chalk.bold(chalk.cyan('[Dry Run]'))
export const errorTag = chalk.bold(chalk.red('[Error]'))
export const warningTag = chalk.bold(chalk.yellow('[Warning]'))
export const warningExclamationSignTag = chalk.bold(chalk.yellow('[!]'))
export const successCheckmarkTag = chalk.bold(chalk.green('✔'))
export const failCrossTag = chalk.bold(chalk.red('✖'))

and if it makes sense feel free to use the helpers in that module as you see fit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines +51 to +53
for file in ./plans/*.json; do
datadog-ci terraform upload plan "$file"
done
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe worth considering adding support directly into the cli for this -- doing this in series will end up being slow if the customer has a lot of plan files

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we have multiple commands supporting glob patterns for multiple files (e.g. sourcemaps upload)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

@Drarig29 Drarig29 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you follow https://github.com/DataDog/datadog-ci/blob/master/CONTRIBUTING.md#things-to-update since you are adding a new command scope?

Comment on lines +51 to +53
for file in ./plans/*.json; do
datadog-ci terraform upload plan "$file"
done
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we have multiple commands supporting glob patterns for multiple files (e.g. sourcemaps upload)

Copy link
Contributor

@ava-silver ava-silver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one optional suggestion, but lgtm!

@vishal-joshi-datadog vishal-joshi-datadog merged commit a48b7d6 into master Feb 27, 2026
26 checks passed
@vishal-joshi-datadog vishal-joshi-datadog deleted the vj/IACP-673 branch February 27, 2026 18:33
@vishal-joshi-datadog vishal-joshi-datadog mentioned this pull request Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

datadog-ci For PRs spanning multiple commands, and repo-wide changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants