@datadog/datadog-ci-plugin-terraform 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # Terraform command
2
+
3
+ This command lets you upload Terraform runtime artifacts (plan and state JSON files) to the Datadog CI intake endpoint for enhanced cloud-to-code mapping and policy evaluation.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ datadog-ci terraform upload [plan|state] <path/to/terraform-file.json> [additional-files...]
9
+ ```
10
+
11
+ ### Arguments
12
+
13
+ - `plan` or `state`: The type of Terraform artifact being uploaded
14
+ - `<path>`: Path to one or more Terraform JSON files (space-separated)
15
+
16
+ ### Optional arguments
17
+
18
+ - `--repo-id` (optional): Repository identifier override (e.g., github.com/datadog/my-repo)
19
+ - `--dry-run` (default: `false`): Run the command without uploading any data to Datadog
20
+ - `--verbose` (default: `false`): Enable verbose logging
21
+ - `--skip-git-metadata-upload` (default: `false`): Skip the upload of git metadata
22
+
23
+ ### Environment variables
24
+
25
+ The following environment variables are required:
26
+
27
+ - `DD_API_KEY`: the API key to use
28
+
29
+ Optional environment variables:
30
+
31
+ - `DD_SITE`: the [Datadog site](https://docs.datadoghq.com/getting_started/site/#access-the-datadog-site) (default: `datadoghq.com`)
32
+ - `DD_GIT_REPOSITORY_URL`: Override for repository URL
33
+ - `DD_REPOSITORY_URL`: Alternative override for repository URL
34
+
35
+ ### Examples
36
+
37
+ ```bash
38
+ # Upload a single Terraform plan file
39
+ datadog-ci terraform upload plan ./terraform-plan.json
40
+
41
+ # Upload multiple Terraform plan files
42
+ datadog-ci terraform upload plan ./plan1.json ./plan2.json ./plan3.json
43
+
44
+ # Upload multiple plan files using glob expansion
45
+ datadog-ci terraform upload plan ./plans/*.json
46
+
47
+ # Upload a Terraform state file
48
+ datadog-ci terraform upload state ./terraform.tfstate
49
+
50
+ # Upload with manual repo-id override
51
+ datadog-ci terraform upload plan ./terraform-plan.json --repo-id "github.com/my-org/my-repo"
52
+
53
+ # Dry run mode
54
+ datadog-ci terraform upload plan ./terraform-plan.json --dry-run
55
+
56
+ # Upload multiple files with verbose logging
57
+ datadog-ci terraform upload plan ./plan1.json ./plan2.json --verbose
58
+ ```
59
+
60
+ ### Git context resolution
61
+
62
+ The Git context is resolved in the following order of priority:
63
+
64
+ 1. CI environment variables
65
+ 2. Current Git repository metadata
66
+ 3. Override environment variables (`DD_GIT_*` variables)
67
+
68
+ The repository identifier (`repo_id`) is resolved in this order:
69
+
70
+ 1. `--repo-id` flag value
71
+ 2. `DD_GIT_REPOSITORY_URL` or `DD_REPOSITORY_URL` environment variable
72
+ 3. Git metadata from the current repository
73
+
74
+ ## Development
75
+
76
+ To test locally, run:
77
+
78
+ ```bash
79
+ yarn launch terraform upload plan /path/to/terraform-plan.json
80
+ ```
81
+
82
+ ## Notes
83
+
84
+ - The command accepts one or more files per invocation. All files must be of the same artifact type (plan or state).
85
+ - Files are automatically gzipped before upload.
86
+ - The command computes a SHA256 hash of each file's content.
87
+ - No client-side validation or filtering of file content is performed (as per RFC requirements).
88
+ - Git metadata is synced only once per invocation, even when uploading multiple files.
package/dist/api.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { AxiosPromise, AxiosRequestConfig, AxiosResponse } from 'axios';
2
+ import { TerraformArtifactPayload } from './interfaces';
3
+ export declare const intakeUrl: string;
4
+ export declare const apiUrl: string;
5
+ export declare const uploadTerraformArtifact: (request: (args: AxiosRequestConfig) => AxiosPromise<AxiosResponse>) => (payload: TerraformArtifactPayload) => Promise<AxiosResponse<AxiosResponse<any, any, {}>, any, {}>>;
6
+ export declare const apiConstructor: (baseIntakeUrl: string, apiKey: string) => {
7
+ uploadTerraformArtifact: (payload: TerraformArtifactPayload) => Promise<AxiosResponse<AxiosResponse<any, any, {}>, any, {}>>;
8
+ };
package/dist/api.js ADDED
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.apiConstructor = exports.uploadTerraformArtifact = exports.apiUrl = exports.intakeUrl = void 0;
16
+ const zlib_1 = require("zlib");
17
+ const api_1 = require("@datadog/datadog-ci-base/helpers/api");
18
+ const utils_1 = require("@datadog/datadog-ci-base/helpers/utils");
19
+ const form_data_1 = __importDefault(require("form-data"));
20
+ const maxBodyLength = Infinity;
21
+ exports.intakeUrl = (0, api_1.getIntakeUrl)('ci-intake');
22
+ exports.apiUrl = (0, api_1.getApiUrl)();
23
+ const uploadTerraformArtifact = (request) => (payload) => __awaiter(void 0, void 0, void 0, function* () {
24
+ const form = new form_data_1.default();
25
+ // Build event envelope according to RFC spec
26
+ const event = Object.assign({ type: 'terraform_artifact', track_type: 'ciiac', schema_version: '1.0', artifact_type: payload.artifactType, artifact_format: 'terraform-json', artifact_sha256: payload.artifactSha256, artifact_size_bytes: payload.artifactSizeBytes }, payload.spanTags);
27
+ // Add repo_id if available
28
+ if (payload.repoId) {
29
+ event.repo_id = payload.repoId;
30
+ }
31
+ // Append event JSON
32
+ form.append('event', JSON.stringify(event), { filename: 'event.json' });
33
+ // Append gzipped file content
34
+ const gzippedContent = yield gzipContent(payload.fileContent);
35
+ form.append('iac_file', gzippedContent, {
36
+ filename: `${payload.artifactType}.json.gz`,
37
+ contentType: 'application/gzip',
38
+ });
39
+ return request({
40
+ data: form,
41
+ headers: form.getHeaders(),
42
+ maxBodyLength,
43
+ method: 'POST',
44
+ url: 'api/v2/ciiac',
45
+ });
46
+ });
47
+ exports.uploadTerraformArtifact = uploadTerraformArtifact;
48
+ const gzipContent = (content) => {
49
+ return new Promise((resolve, reject) => {
50
+ const chunks = [];
51
+ const gzip = (0, zlib_1.createGzip)();
52
+ gzip.on('data', (chunk) => chunks.push(chunk));
53
+ gzip.on('end', () => resolve(Buffer.concat(chunks)));
54
+ gzip.on('error', reject);
55
+ gzip.write(content);
56
+ gzip.end();
57
+ });
58
+ };
59
+ const apiConstructor = (baseIntakeUrl, apiKey) => {
60
+ const requestIntake = (0, utils_1.getRequestBuilder)({ baseUrl: baseIntakeUrl, apiKey });
61
+ return {
62
+ uploadTerraformArtifact: (0, exports.uploadTerraformArtifact)(requestIntake),
63
+ };
64
+ };
65
+ exports.apiConstructor = apiConstructor;
66
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,+BAA+B;AAI/B,8DAA4E;AAC5E,kEAAwE;AACxE,0DAAgC;AAIhC,MAAM,aAAa,GAAG,QAAQ,CAAA;AAEjB,QAAA,SAAS,GAAG,IAAA,kBAAY,EAAC,WAAW,CAAC,CAAA;AACrC,QAAA,MAAM,GAAG,IAAA,eAAS,GAAE,CAAA;AAE1B,MAAM,uBAAuB,GAClC,CAAC,OAAkE,EAAE,EAAE,CAAC,CAAO,OAAiC,EAAE,EAAE;IAClH,MAAM,IAAI,GAAG,IAAI,mBAAQ,EAAE,CAAA;IAE3B,6CAA6C;IAC7C,MAAM,KAAK,mBACT,IAAI,EAAE,oBAAoB,EAC1B,UAAU,EAAE,OAAO,EACnB,cAAc,EAAE,KAAK,EACrB,aAAa,EAAE,OAAO,CAAC,YAAY,EACnC,eAAe,EAAE,gBAAgB,EACjC,eAAe,EAAE,OAAO,CAAC,cAAc,EACvC,mBAAmB,EAAE,OAAO,CAAC,iBAAiB,IAC3C,OAAO,CAAC,QAAQ,CACpB,CAAA;IAED,2BAA2B;IAC3B,IAAI,OAAO,CAAC,MAAM,EAAE;QAClB,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;KAC/B;IAED,oBAAoB;IACpB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAC,QAAQ,EAAE,YAAY,EAAC,CAAC,CAAA;IAErE,8BAA8B;IAC9B,MAAM,cAAc,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAC7D,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,cAAc,EAAE;QACtC,QAAQ,EAAE,GAAG,OAAO,CAAC,YAAY,UAAU;QAC3C,WAAW,EAAE,kBAAkB;KAChC,CAAC,CAAA;IAEF,OAAO,OAAO,CAAC;QACb,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE;QAC1B,aAAa;QACb,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,cAAc;KACpB,CAAC,CAAA;AACJ,CAAC,CAAA,CAAA;AAtCU,QAAA,uBAAuB,2BAsCjC;AAEH,MAAM,WAAW,GAAG,CAAC,OAAe,EAAmB,EAAE;IACvD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAA;QAC3B,MAAM,IAAI,GAAG,IAAA,iBAAU,GAAE,CAAA;QAEzB,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;QAC9C,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACpD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAExB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACnB,IAAI,CAAC,GAAG,EAAE,CAAA;IACZ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAEM,MAAM,cAAc,GAAG,CAAC,aAAqB,EAAE,MAAc,EAAE,EAAE;IACtE,MAAM,aAAa,GAAG,IAAA,yBAAiB,EAAC,EAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAC,CAAC,CAAA;IAEzE,OAAO;QACL,uBAAuB,EAAE,IAAA,+BAAuB,EAAC,aAAa,CAAC;KAChE,CAAA;AACH,CAAC,CAAA;AANY,QAAA,cAAc,kBAM1B"}
@@ -0,0 +1,11 @@
1
+ import { TerraformUploadCommand } from '@datadog/datadog-ci-base/commands/terraform/upload';
2
+ export declare class PluginCommand extends TerraformUploadCommand {
3
+ private config;
4
+ private logger;
5
+ private git;
6
+ execute(): Promise<1 | 0>;
7
+ private syncGitMetadata;
8
+ private uploadToGitDB;
9
+ private uploadTerraformArtifact;
10
+ private getSpanTags;
11
+ }
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.PluginCommand = void 0;
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const git_1 = require("@datadog/datadog-ci-base/commands/git-metadata/git");
18
+ const gitdb_1 = require("@datadog/datadog-ci-base/commands/git-metadata/gitdb");
19
+ const library_1 = require("@datadog/datadog-ci-base/commands/git-metadata/library");
20
+ const upload_1 = require("@datadog/datadog-ci-base/commands/terraform/upload");
21
+ const constants_1 = require("@datadog/datadog-ci-base/constants");
22
+ const ci_1 = require("@datadog/datadog-ci-base/helpers/ci");
23
+ const env_1 = require("@datadog/datadog-ci-base/helpers/env");
24
+ const fips_1 = require("@datadog/datadog-ci-base/helpers/fips");
25
+ const format_git_span_data_1 = require("@datadog/datadog-ci-base/helpers/git/format-git-span-data");
26
+ const id_1 = __importDefault(require("@datadog/datadog-ci-base/helpers/id"));
27
+ const logger_1 = require("@datadog/datadog-ci-base/helpers/logger");
28
+ const retry_1 = require("@datadog/datadog-ci-base/helpers/retry");
29
+ const user_provided_git_1 = require("@datadog/datadog-ci-base/helpers/user-provided-git");
30
+ const utils_1 = require("@datadog/datadog-ci-base/helpers/utils");
31
+ const chalk_1 = __importDefault(require("chalk"));
32
+ const api_1 = require("../api");
33
+ const renderer_1 = require("../renderer");
34
+ const utils_2 = require("../utils");
35
+ class PluginCommand extends upload_1.TerraformUploadCommand {
36
+ constructor() {
37
+ var _a, _b;
38
+ super(...arguments);
39
+ this.config = {
40
+ apiKey: process.env.DATADOG_API_KEY || process.env.DD_API_KEY,
41
+ fips: (_a = (0, env_1.toBoolean)(process.env[constants_1.FIPS_ENV_VAR])) !== null && _a !== void 0 ? _a : false,
42
+ fipsIgnoreError: (_b = (0, env_1.toBoolean)(process.env[constants_1.FIPS_IGNORE_ERROR_ENV_VAR])) !== null && _b !== void 0 ? _b : false,
43
+ };
44
+ this.logger = new logger_1.Logger((s) => this.context.stdout.write(s), logger_1.LogLevel.INFO);
45
+ this.git = undefined;
46
+ }
47
+ execute() {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ (0, fips_1.enableFips)(this.fips || this.config.fips, this.fipsIgnoreError || this.config.fipsIgnoreError);
50
+ this.logger.setLogLevel(this.verbose ? logger_1.LogLevel.DEBUG : logger_1.LogLevel.INFO);
51
+ this.logger.setShouldIncludeTime(this.verbose);
52
+ // Validate API key
53
+ if (!this.config.apiKey) {
54
+ this.logger.error(`Neither ${chalk_1.default.red.bold('DATADOG_API_KEY')} nor ${chalk_1.default.red.bold('DD_API_KEY')} is in your environment.`);
55
+ return 1;
56
+ }
57
+ // Initialize git if in a repository
58
+ const isGitRepository = yield (0, library_1.isGitRepo)();
59
+ if (isGitRepository) {
60
+ this.git = yield (0, git_1.newSimpleGit)();
61
+ }
62
+ // Sync git metadata if needed (only once for all files)
63
+ if (!this.skipGitMetadataUpload && isGitRepository) {
64
+ yield this.syncGitMetadata();
65
+ }
66
+ // Upload terraform artifacts
67
+ let hasFailures = false;
68
+ for (const filePath of this.filePaths) {
69
+ const exitCode = yield this.uploadTerraformArtifact(filePath);
70
+ if (exitCode !== 0) {
71
+ hasFailures = true;
72
+ }
73
+ }
74
+ return hasFailures ? 1 : 0;
75
+ });
76
+ }
77
+ syncGitMetadata() {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ const traceId = (0, id_1.default)();
80
+ const requestBuilder = (0, utils_1.getRequestBuilder)({
81
+ baseUrl: api_1.apiUrl,
82
+ apiKey: this.config.apiKey,
83
+ headers: new Map([
84
+ ['x-datadog-trace-id', traceId],
85
+ ['x-datadog-parent-id', traceId],
86
+ ]),
87
+ });
88
+ try {
89
+ this.logger.info(`${this.dryRun ? '[DRYRUN] ' : ''}Syncing git metadata...`);
90
+ let elapsed = 0;
91
+ if (!this.dryRun) {
92
+ elapsed = yield (0, utils_1.timedExecAsync)(this.uploadToGitDB.bind(this), { requestBuilder });
93
+ }
94
+ this.logger.info((0, renderer_1.renderSuccessfulGitDBSync)(this.dryRun, elapsed));
95
+ }
96
+ catch (err) {
97
+ this.logger.info((0, renderer_1.renderFailedGitDBSync)(err));
98
+ }
99
+ });
100
+ }
101
+ uploadToGitDB(opts) {
102
+ return __awaiter(this, void 0, void 0, function* () {
103
+ if (!this.git) {
104
+ return;
105
+ }
106
+ yield (0, gitdb_1.uploadToGitDB)(this.logger, opts.requestBuilder, this.git, this.dryRun);
107
+ });
108
+ }
109
+ uploadTerraformArtifact(filePath) {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ this.logger.info((0, renderer_1.renderCommandInfo)(this.artifactType, filePath, this.dryRun));
112
+ // Validate file exists and is readable
113
+ if (!(0, utils_2.validateFilePath)(filePath)) {
114
+ this.context.stderr.write((0, renderer_1.renderInvalidFile)(filePath, 'File not found or not readable'));
115
+ return 1;
116
+ }
117
+ // Read and validate JSON structure
118
+ const fileContent = fs_1.default.readFileSync(filePath, 'utf8');
119
+ if (!(0, utils_2.validateJsonStructure)(fileContent)) {
120
+ this.context.stderr.write((0, renderer_1.renderInvalidFile)(filePath, 'Invalid JSON structure'));
121
+ return 1;
122
+ }
123
+ // Compute file hash and size
124
+ const artifactSha256 = (0, utils_2.computeFileHash)(fileContent);
125
+ const artifactSizeBytes = Buffer.byteLength(fileContent, 'utf8');
126
+ const spanTags = yield this.getSpanTags();
127
+ const api = (0, api_1.apiConstructor)(api_1.intakeUrl, this.config.apiKey);
128
+ // Build payload
129
+ const payload = {
130
+ artifactType: this.artifactType,
131
+ filePath,
132
+ fileContent,
133
+ artifactSha256,
134
+ artifactSizeBytes,
135
+ spanTags,
136
+ repoId: (0, utils_2.resolveRepoId)(this.repoId, spanTags),
137
+ };
138
+ try {
139
+ // Upload
140
+ if (this.dryRun) {
141
+ this.logger.info((0, renderer_1.renderDryRunUpload)(payload));
142
+ }
143
+ else {
144
+ yield (0, retry_1.retryRequest)(() => api.uploadTerraformArtifact(payload), {
145
+ onRetry: (e, attempt) => {
146
+ this.logger.warn(`Retry attempt ${attempt} for ${filePath}: ${e.message}`);
147
+ },
148
+ retries: 5,
149
+ });
150
+ this.logger.info((0, renderer_1.renderSuccessfulUpload)(filePath));
151
+ }
152
+ return 0;
153
+ }
154
+ catch (error) {
155
+ this.context.stderr.write((0, renderer_1.renderFailedUpload)(filePath, error));
156
+ return 1;
157
+ }
158
+ });
159
+ }
160
+ getSpanTags() {
161
+ return __awaiter(this, void 0, void 0, function* () {
162
+ const ciSpanTags = (0, ci_1.getCISpanTags)();
163
+ const gitSpanTags = yield (0, format_git_span_data_1.getGitMetadata)();
164
+ const userGitSpanTags = (0, user_provided_git_1.getUserGitSpanTags)();
165
+ return Object.assign(Object.assign(Object.assign({}, gitSpanTags), ciSpanTags), userGitSpanTags);
166
+ });
167
+ }
168
+ }
169
+ exports.PluginCommand = PluginCommand;
170
+ //# sourceMappingURL=upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/commands/upload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { AxiosPromise, AxiosResponse } from 'axios';
2
+ import { SpanTags } from '@datadog/datadog-ci-base/helpers/interfaces';
3
+ export interface TerraformArtifactPayload {
4
+ artifactType: 'plan' | 'state';
5
+ filePath: string;
6
+ fileContent: string;
7
+ artifactSha256: string;
8
+ artifactSizeBytes: number;
9
+ spanTags: SpanTags;
10
+ repoId?: string;
11
+ }
12
+ export interface APIHelper {
13
+ uploadTerraformArtifact(payload: TerraformArtifactPayload): AxiosPromise<AxiosResponse>;
14
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=interfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import { TerraformArtifactPayload } from './interfaces';
2
+ export declare const renderCommandInfo: (artifactType: string, filePath: string, dryRun: boolean) => string;
3
+ export declare const renderDryRunUpload: (payload: TerraformArtifactPayload) => string;
4
+ export declare const renderSuccessfulUpload: (filePath: string) => string;
5
+ export declare const renderFailedUpload: (filePath: string, error: any) => string;
6
+ export declare const renderInvalidFile: (filePath: string, reason: string) => string;
7
+ export declare const renderSuccessfulGitDBSync: (dryRun: boolean, elapsed: number) => string;
8
+ export declare const renderFailedGitDBSync: (error: any) => string;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.renderFailedGitDBSync = exports.renderSuccessfulGitDBSync = exports.renderInvalidFile = exports.renderFailedUpload = exports.renderSuccessfulUpload = exports.renderDryRunUpload = exports.renderCommandInfo = void 0;
7
+ const renderer_1 = require("@datadog/datadog-ci-base/helpers/renderer");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const renderCommandInfo = (artifactType, filePath, dryRun) => {
10
+ const prefix = dryRun ? `${renderer_1.dryRunTag} ` : '';
11
+ return `${prefix}Uploading Terraform ${artifactType} file: ${filePath}\n`;
12
+ };
13
+ exports.renderCommandInfo = renderCommandInfo;
14
+ const renderDryRunUpload = (payload) => {
15
+ return `${renderer_1.dryRunTag} Would upload: ${payload.filePath}\n`;
16
+ };
17
+ exports.renderDryRunUpload = renderDryRunUpload;
18
+ const renderSuccessfulUpload = (filePath) => {
19
+ return `${renderer_1.successCheckmarkTag} Successfully uploaded: ${filePath}\n`;
20
+ };
21
+ exports.renderSuccessfulUpload = renderSuccessfulUpload;
22
+ const renderFailedUpload = (filePath, error) => {
23
+ const message = (error === null || error === void 0 ? void 0 : error.message) || 'Unknown error';
24
+ return `${renderer_1.failCrossTag} Failed to upload ${filePath}: ${message}\n`;
25
+ };
26
+ exports.renderFailedUpload = renderFailedUpload;
27
+ const renderInvalidFile = (filePath, reason) => {
28
+ return `${renderer_1.failCrossTag} Invalid file ${filePath}: ${reason}\n`;
29
+ };
30
+ exports.renderInvalidFile = renderInvalidFile;
31
+ const renderSuccessfulGitDBSync = (dryRun, elapsed) => {
32
+ const prefix = dryRun ? `${renderer_1.dryRunTag} ` : '';
33
+ return `${prefix}${renderer_1.successCheckmarkTag} Git metadata synced (${elapsed}ms)\n`;
34
+ };
35
+ exports.renderSuccessfulGitDBSync = renderSuccessfulGitDBSync;
36
+ const renderFailedGitDBSync = (error) => {
37
+ const message = (error === null || error === void 0 ? void 0 : error.message) || 'Unknown error';
38
+ return chalk_1.default.yellow(`⚠ Failed to sync git metadata: ${message}\n`);
39
+ };
40
+ exports.renderFailedGitDBSync = renderFailedGitDBSync;
41
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":";;;;;;AAAA,wEAAsG;AACtG,kDAAyB;AAIlB,MAAM,iBAAiB,GAAG,CAAC,YAAoB,EAAE,QAAgB,EAAE,MAAe,EAAU,EAAE;IACnG,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,oBAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;IAE5C,OAAO,GAAG,MAAM,uBAAuB,YAAY,UAAU,QAAQ,IAAI,CAAA;AAC3E,CAAC,CAAA;AAJY,QAAA,iBAAiB,qBAI7B;AAEM,MAAM,kBAAkB,GAAG,CAAC,OAAiC,EAAU,EAAE;IAC9E,OAAO,GAAG,oBAAS,kBAAkB,OAAO,CAAC,QAAQ,IAAI,CAAA;AAC3D,CAAC,CAAA;AAFY,QAAA,kBAAkB,sBAE9B;AAEM,MAAM,sBAAsB,GAAG,CAAC,QAAgB,EAAU,EAAE;IACjE,OAAO,GAAG,8BAAmB,2BAA2B,QAAQ,IAAI,CAAA;AACtE,CAAC,CAAA;AAFY,QAAA,sBAAsB,0BAElC;AAEM,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAE,KAAU,EAAU,EAAE;IACzE,MAAM,OAAO,GAAG,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,KAAI,eAAe,CAAA;IAEjD,OAAO,GAAG,uBAAY,qBAAqB,QAAQ,KAAK,OAAO,IAAI,CAAA;AACrE,CAAC,CAAA;AAJY,QAAA,kBAAkB,sBAI9B;AAEM,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAE,MAAc,EAAU,EAAE;IAC5E,OAAO,GAAG,uBAAY,iBAAiB,QAAQ,KAAK,MAAM,IAAI,CAAA;AAChE,CAAC,CAAA;AAFY,QAAA,iBAAiB,qBAE7B;AAEM,MAAM,yBAAyB,GAAG,CAAC,MAAe,EAAE,OAAe,EAAU,EAAE;IACpF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,oBAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;IAE5C,OAAO,GAAG,MAAM,GAAG,8BAAmB,yBAAyB,OAAO,OAAO,CAAA;AAC/E,CAAC,CAAA;AAJY,QAAA,yBAAyB,6BAIrC;AAEM,MAAM,qBAAqB,GAAG,CAAC,KAAU,EAAU,EAAE;IAC1D,MAAM,OAAO,GAAG,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,OAAO,KAAI,eAAe,CAAA;IAEjD,OAAO,eAAK,CAAC,MAAM,CAAC,kCAAkC,OAAO,IAAI,CAAC,CAAA;AACpE,CAAC,CAAA;AAJY,QAAA,qBAAqB,yBAIjC"}
@@ -0,0 +1,11 @@
1
+ import { SpanTags } from '@datadog/datadog-ci-base/helpers/interfaces';
2
+ export declare const validateFilePath: (filePath: string) => boolean;
3
+ export declare const validateJsonStructure: (content: string) => boolean;
4
+ export declare const computeFileHash: (content: string) => string;
5
+ /**
6
+ * Resolve repo_id with the following priority:
7
+ * 1. Explicit flag value (--repo-id)
8
+ * 2. Environment variable (DD_GIT_REPOSITORY_URL or similar)
9
+ * 3. Git metadata extracted from spanTags
10
+ */
11
+ export declare const resolveRepoId: (flagValue: string | undefined, spanTags: SpanTags) => string | undefined;
package/dist/utils.js ADDED
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveRepoId = exports.computeFileHash = exports.validateJsonStructure = exports.validateFilePath = void 0;
7
+ const crypto_1 = require("crypto");
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const tags_1 = require("@datadog/datadog-ci-base/helpers/tags");
10
+ const validateFilePath = (filePath) => {
11
+ try {
12
+ return fs_1.default.existsSync(filePath) && fs_1.default.statSync(filePath).isFile();
13
+ }
14
+ catch (_a) {
15
+ return false;
16
+ }
17
+ };
18
+ exports.validateFilePath = validateFilePath;
19
+ const validateJsonStructure = (content) => {
20
+ try {
21
+ JSON.parse(content);
22
+ return true;
23
+ }
24
+ catch (_a) {
25
+ return false;
26
+ }
27
+ };
28
+ exports.validateJsonStructure = validateJsonStructure;
29
+ const computeFileHash = (content) => {
30
+ const hash = (0, crypto_1.createHash)('sha256');
31
+ hash.update(content);
32
+ return hash.digest('hex');
33
+ };
34
+ exports.computeFileHash = computeFileHash;
35
+ /**
36
+ * Resolve repo_id with the following priority:
37
+ * 1. Explicit flag value (--repo-id)
38
+ * 2. Environment variable (DD_GIT_REPOSITORY_URL or similar)
39
+ * 3. Git metadata extracted from spanTags
40
+ */
41
+ const resolveRepoId = (flagValue, spanTags) => {
42
+ if (flagValue) {
43
+ return flagValue;
44
+ }
45
+ // Try environment variables
46
+ const envRepoId = process.env.DD_GIT_REPOSITORY_URL || process.env.DD_REPOSITORY_URL;
47
+ if (envRepoId) {
48
+ return envRepoId;
49
+ }
50
+ // Fall back to git metadata
51
+ return spanTags[tags_1.GIT_REPOSITORY_URL];
52
+ };
53
+ exports.resolveRepoId = resolveRepoId;
54
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;AAAA,mCAAiC;AACjC,4CAAmB;AAGnB,gEAAwE;AAEjE,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAW,EAAE;IAC5D,IAAI;QACF,OAAO,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,YAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAA;KACjE;IAAC,WAAM;QACN,OAAO,KAAK,CAAA;KACb;AACH,CAAC,CAAA;AANY,QAAA,gBAAgB,oBAM5B;AAEM,MAAM,qBAAqB,GAAG,CAAC,OAAe,EAAW,EAAE;IAChE,IAAI;QACF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAEnB,OAAO,IAAI,CAAA;KACZ;IAAC,WAAM;QACN,OAAO,KAAK,CAAA;KACb;AACH,CAAC,CAAA;AARY,QAAA,qBAAqB,yBAQjC;AAEM,MAAM,eAAe,GAAG,CAAC,OAAe,EAAU,EAAE;IACzD,MAAM,IAAI,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAA;IACjC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAEpB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC3B,CAAC,CAAA;AALY,QAAA,eAAe,mBAK3B;AAED;;;;;GAKG;AACI,MAAM,aAAa,GAAG,CAAC,SAA6B,EAAE,QAAkB,EAAsB,EAAE;IACrG,IAAI,SAAS,EAAE;QACb,OAAO,SAAS,CAAA;KACjB;IAED,4BAA4B;IAC5B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAA;IACpF,IAAI,SAAS,EAAE;QACb,OAAO,SAAS,CAAA;KACjB;IAED,4BAA4B;IAC5B,OAAO,QAAQ,CAAC,yBAAkB,CAAC,CAAA;AACrC,CAAC,CAAA;AAbY,QAAA,aAAa,iBAazB"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@datadog/datadog-ci-plugin-terraform",
3
+ "version": "0.0.1",
4
+ "description": "Datadog CI plugin for `terraform` commands",
5
+ "license": "Apache-2.0",
6
+ "keywords": [
7
+ "datadog",
8
+ "datadog-ci",
9
+ "iac",
10
+ "plugin",
11
+ "terraform"
12
+ ],
13
+ "homepage": "https://github.com/DataDog/datadog-ci/tree/master/packages/plugin-terraform",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/DataDog/datadog-ci.git",
17
+ "directory": "packages/plugin-terraform"
18
+ },
19
+ "exports": {
20
+ "./package.json": "./package.json",
21
+ "./commands/*": {
22
+ "development": "./src/commands/*.ts",
23
+ "default": "./dist/commands/*.js"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist/**/*",
28
+ "README",
29
+ "LICENSE"
30
+ ],
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "scripts": {
35
+ "build": "yarn package:clean; yarn package:build",
36
+ "lint": "yarn package:lint",
37
+ "prepack": "yarn package:clean-dist"
38
+ },
39
+ "peerDependencies": {
40
+ "@datadog/datadog-ci-base": "5.9.0"
41
+ },
42
+ "dependencies": {
43
+ "axios": "^1.13.5",
44
+ "chalk": "3.0.0",
45
+ "form-data": "^4.0.4",
46
+ "simple-git": "3.16.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/jest": "29.5.3",
50
+ "upath": "^2.0.1"
51
+ }
52
+ }