Repository: awslabs/aws-ddk (language: python)

Issue:
cicd: additional install commands, alongside `cdk_language`
Allow additional install commands, appended to the existing `cdk_language` command that's associated.
```py
pipeline_stack = CICDPipelineStack(
    app,
    id="Example_pipeline",
    environment_id="prod",
    pipeline_name="Example_pipeline",
    env=Configurator.get_environment(config_path="./ddk.json", environment_id=environment_id),
    cdk_language="python",
)
```
`cdk_langauge` causes the `pip install -r requirements.txt` to be added. However, there is an additional need for my use case to add parameters alongside the `pip install` command. Specifically, `--extra-index-url` which will look for private registries. We cannot use CodeArtifact due to the nature of our business, however by using `--extra-index-url`, we could install our packages from our own private pypi repository.
A workaround at the moment is to remove `cdk_language` and default it to `typescript` with a `package.json` file in the project directory. Thereafter, we can use `additional_install_commands`.
 ```py
pipeline_stack.add_synth_action(
    additional_install_commands=[
        "pip install -r requirements.txt --extra-index-url https://some-other-url --another-parameter 'another value'"
    ],
)
```
Potentially, an implementation could be `cdk_language_parameters` to parse additional parameters, appended to the `pip install` or `npm install` commands. This could be included in the `add_synth_action`, such as
 ```py
pipeline_stack.add_synth_action(
    cdk_langauge_parameters={
      "--extra-index-url": "this_url",
      "--another-parameter": "another value"
    }
)
```


Discussion / hints:

Fix patch:
diff --git a/API.md b/API.md
index c7aa0638..fe2fbad9 100644
--- a/API.md
+++ b/API.md
@@ -13160,6 +13160,7 @@ const synthActionProps: SynthActionProps = { ... }
 | **Name** | **Type** | **Description** |
 | --- | --- | --- |
 | <code><a href="#aws-ddk-core.SynthActionProps.property.additionalInstallCommands">additionalInstallCommands</a></code> | <code>string[]</code> | Additional install commands. |
+| <code><a href="#aws-ddk-core.SynthActionProps.property.cdkLanguageCommandLineArguments">cdkLanguageCommandLineArguments</a></code> | <code>{[ key: string ]: string}</code> | Additional command line arguements to append to the install command of the `cdk_langauge` that is specified. |
 | <code><a href="#aws-ddk-core.SynthActionProps.property.cdkVersion">cdkVersion</a></code> | <code>string</code> | CDK versio to use during the synth action. |
 | <code><a href="#aws-ddk-core.SynthActionProps.property.codeartifactDomain">codeartifactDomain</a></code> | <code>string</code> | Name of the CodeArtifact domain. |
 | <code><a href="#aws-ddk-core.SynthActionProps.property.codeartifactDomainOwner">codeartifactDomainOwner</a></code> | <code>string</code> | CodeArtifact domain owner account. |
@@ -13182,6 +13183,19 @@ Additional install commands.
 
 ---
 
+##### `cdkLanguageCommandLineArguments`<sup>Optional</sup> <a name="cdkLanguageCommandLineArguments" id="aws-ddk-core.SynthActionProps.property.cdkLanguageCommandLineArguments"></a>
+
+```typescript
+public readonly cdkLanguageCommandLineArguments: {[ key: string ]: string};
+```
+
+- *Type:* {[ key: string ]: string}
+- *Default:* No command line arguments are appended
+
+Additional command line arguements to append to the install command of the `cdk_langauge` that is specified.
+
+---
+
 ##### `cdkVersion`<sup>Optional</sup> <a name="cdkVersion" id="aws-ddk-core.SynthActionProps.property.cdkVersion"></a>
 
 ```typescript
diff --git a/src/cicd/pipelines.ts b/src/cicd/pipelines.ts
index 1afdd617..c3f0f063 100644
--- a/src/cicd/pipelines.ts
+++ b/src/cicd/pipelines.ts
@@ -67,6 +67,12 @@ export interface SynthActionProps {
    * Additional install commands.
    */
   readonly additionalInstallCommands?: string[];
+  /**
+   * Additional command line arguements to append to the install command of the `cdk_langauge` that is specified.
+   *
+   * @default - No command line arguments are appended
+   */
+  readonly cdkLanguageCommandLineArguments?: { [key: string]: string };
 }
 
 /**
@@ -376,11 +382,18 @@ export class CICDPipelineStack extends BaseStack {
    * @returns reference to this pipeline.
    */
   addSynthAction(props: SynthActionProps = {}) {
-    const languageInstallCommand: any = {
+    const languageInstallCommands: any = {
       typescript: "npm install",
       python: "pip install -r requirements.txt",
     };
 
+    let languageInstallCommand = languageInstallCommands[this.cdkLanguage];
+    if (props.cdkLanguageCommandLineArguments) {
+      for (const [argument, value] of Object.entries(props.cdkLanguageCommandLineArguments)) {
+        languageInstallCommand += ` ${argument} ${value}`;
+      }
+    }
+
     this.synthAction =
       props.synthAction ||
       CICDActions.getSynthAction({
@@ -395,8 +408,8 @@ export class CICDPipelineStack extends BaseStack {
         codeartifactDomain: props.codeartifactDomain,
         codeartifactDomainOwner: props.codeartifactDomainOwner,
         additionalInstallCommands: props.additionalInstallCommands
-          ? [languageInstallCommand[this.cdkLanguage]].concat(props.additionalInstallCommands)
-          : [languageInstallCommand[this.cdkLanguage]],
+          ? [languageInstallCommand].concat(props.additionalInstallCommands)
+          : [languageInstallCommand],
       });
     return this;
   }


Test patch:
diff --git a/test/cicd-pipeline-stack.test.ts b/test/cicd-pipeline-stack.test.ts
index 4db94a92..171685cf 100644
--- a/test/cicd-pipeline-stack.test.ts
+++ b/test/cicd-pipeline-stack.test.ts
@@ -701,3 +701,23 @@ test("CICDPipeline with different environments", () => {
   const template = Template.fromStack(stack);
   template.resourceCountIs("AWS::CodePipeline::Pipeline", 1);
 });
+
+test("CICDPipeline with additional cdk langauge comamnds", () => {
+  const app = new cdk.App();
+  const stack = new CICDPipelineStack(app, "dummy-pipeline", { environmentId: "dev", pipelineName: "dummy-pipeline" })
+    .addSourceAction({ repositoryName: "dummy-repository" })
+    .addSynthAction({
+      cdkLanguageCommandLineArguments: {
+        "--foo": "bar",
+        "--bar": "foo",
+      },
+    })
+    .buildPipeline()
+    .synth();
+  const template = Template.fromStack(stack);
+  template.hasResourceProperties("AWS::CodeBuild::Project", {
+    Source: {
+      BuildSpec: Match.stringLikeRegexp("npm install --foo bar --bar foo"),
+    },
+  });
+});