hallcor.pulumi-projen-project-types 0.0.64
@hallcor/pulumi-projen-project-types
License: Apache-2.0
Requires Python: ~=3.9

# Pulumi Projen Project Types

Collection of [Projen](https://github.com/projen/projen) project types for use
with [Pulumi](https://www.pulumi.com/)

## Getting Started

*projen* doesn't need to be installed. You will be using
[npx](https://docs.npmjs.com/cli/v7/commands/npx) to run *projen* which takes
care of all required setup steps.

To create a new project, run the following command and follow the instructions:

```console
$ mkdir my-project
$ cd my-project
$ npx projen new --from @hallcor/pulumi-projen-project-types PROJECT-TYPE
🤖 Synthesizing project...
...
```

Once your project is created, you can configure your project by editing
`.projenrc.ts` or `.projenrc.py` and re-running `npx projen` to synthesize again.

> The files generated by *projen* are considered an "implementation detail" and
> *projen* protects them from being manually edited (most files are marked
> read-only, and an "anti tamper" check is configured in the CI build workflow
> to ensure that files are not updated during build).

## Projen commands

For the TypeScript based projects the project commands can be viewed an run
using the package manager (e.g. `yarn build`, `yarn package`, etc). For
non-TypeScript based projects (i.e. Python) you can use projen to view and run
project commands.

Projen is built around a standard build process for all projects. Each project
will have these standard [tasks](https://projen.io/docs/concepts/tasks).

1. `default`: The "default" task that executes projen and synthesizes the project
2. `pre-compile`: Task that runs prior to `compile`
3. `compile`: Compiles the project (e.g. `tsc --build` for TypeScript projects)
4. `post-compile`: Task that runs after `compile`
5. `test`: Task that runs the project tests
6. `package`: Task that runs steps to package the project for publishing

There is also a standard `build` task the chains the above 6 tasks in order.

There is a great [tasks guide] where you can find more information on adding new
tasks, editing existing tasks, etc.

**List available commands**

```console
$ npx projen --help
projen [command]

Commands:
  projen new [PROJECT-TYPE-NAME] [OPTIONS]  Creates a new projen project

                                            For a complete list of the available options for a specific project type, run:
                                            projen new [PROJECT-TYPE-NAME] --help
  projen build                              Full release build
  projen bump                               Bumps version based on latest git tag and generates a changelog entry
  projen clobber                            hard resets to HEAD of origin and cleans the local repo
  projen compile                            Only compile
  projen default                            Synthesize project files
  projen dist
  projen eject                              Remove projen from the project
  projen install                            Install and upgrade dependencies
  projen package                            Creates the distribution package
  projen post-compile                       Runs after successful compilation
  projen pre-compile                        Prepare the project for compilation
  projen publish:git                        Prepends the release changelog onto the project changelog, creates a release commit, and tags the release
  projen release                            Prepare a release from "main" branch
  projen test                               Run tests
  projen unbump                             Restores version to 0.0.0
  projen completion                         generate completion script

Options:
      --post     Run post-synthesis steps such as installing dependencies. Use --no-post to skip                                                                                                                                     [boolean] [default: true]
  -w, --watch    Keep running and resynthesize when projenrc changes                                                                                                                                                                [boolean] [default: false]
      --debug    Debug logs                                                                                                                                                                                                         [boolean] [default: false]
      --rc       path to .projenrc.js file                                                                                                                        [deprecated] [string] [default: "/Users/chall/personal/pulumi-lambda-builders/.projenrc.js"]
      --help     Show help                                                                                                                                                                                                                           [boolean]
      --version  Show version number

```

**Run a specific command**

```console
$ npx projen build
```

**Inspect a specific command**

```console
$ npx projen build -i
description: Full release build
- default
  description: Synthesize project files
  - exec: python .projenrc.py
- pre-compile
  description: Prepare the project for compilation
- compile
  description: Only compile
- post-compile
  description: Runs after successful compilation
- test
  description: Run tests
  - exec: npm ci
  - exec: pytest
- package
  description: Creates the distribution package
  - dist
    - exec: mkdir -p dist
    - exec: cp version.json dist/
    - exec: git checkout version.json
```

## Project types

Currently supported project types

* `PythonComponent`: Creates a Pulumi Python Component project
* `TypeScriptComponent`: Creates a Pulumi TypeScript Component project

### Pulumi Python Component

```console
$ mkdir my-python-component
$ cd my-python-component
$ npx projen new --from @hallcor/pulumi-projen-project-types python_component
```

#### Example

```python
from hallcor.pulumi_projen_project_types import PythonComponent

project = PythonComponent(
    module_name="pulumi_lambda_builders",
    component_name="lambda-builders",
    name="pulumi-lambda-builders",
    version="0.1.0",
    deps=[
        "aws_lambda_builders",
    ],
    dev_deps=[
        "pyfakefs",
        "numpy",
        "hallcor.pulumi-projen-project-types",
    ],
)

project.synth()
```

#### Configuration Options

* [componentName](https://github.com/corymhall/pulumi-projen-project-types/blob/main/API.md#componentnameoptional-)
  By default the `name` of the of the Pulumi component will be taken from the
  project `name`. This can be overridden by using the `componentName` property.

For a full list of input properties supported see the [Input Property Reference](https://github.com/corymhall/pulumi-projen-project-types/blob/main/API.md#typescriptprojectprops-)

* [pulumi_python_options](https://github.com/corymhall/pulumi-projen-project-types/blob/main/API.md#pulumipythonoptionsoptional-)
  This can be used to override some of the default Pulumi options. For example you
  can specify a specific version of `pulumi` to use.

```python

project = PythonComponent(
    ...,
    pulumi_python_options=PulumiPythonOptions(
        pulumi_version=">=3.159 <4.0" # this is the default value
    ),
)
```

For publishing related options see the [publishing section](#publishing)

### Pulumi TypeScript Component

```console
$ mkdir my-python-component
$ cd my-python-component
$ npx projen new --from @hallcor/pulumi-projen-project-types type_script_component --name my-component
```

#### Example

```python
import { TypeScriptComponent } from '@hallcor/pulumi-projen-project-types';

const project = new TypeScriptComponent({
  defaultReleaseBranch: 'main',
  devDeps: [
    '@hallcor/pulumi-projen-project-types',
  ],
  name: 'my-component',
  projenrcTs: true,

  // deps: [],                /* Runtime dependencies of this module. */
  // description: undefined,  /* The description is just a string that helps people understand the purpose of the package. */
  // packageName: undefined,  /* The "name" in package.json. */
});
project.synth();
```

#### Configuration Options

* TODO

## Publishing

The Pulumi Component project types also setup publishing workflows to publish
git tags and GitHub releases. By default these will

> [!IMPORTANT]
> The publishing workflows rely on [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version)
> which means your commits must follow [Conventional Commits](https://conventionalcommits.org/)

* Create an annotated tag on push to the `main` branch
* Create a GitHub release for the tag when the tag is created

### Release Trigger

By default the project will publish a new tag on every commit to the `main`
branch. This can be configured via the `releaseTrigger` option.

* `scheduled`: Run the release workflow on a schedule
* `manual`: Creates a publish task which can be run locally to publish a tag
* `continuous`: Run the release workflow on every commit to the `main` branch

**On a schedule**

```python
new TypeScriptComponent({
  ...,
  releaseTrigger: ReleaseTrigger.scheduled({ schedule: '0 0 * * 2' }), // run every tuesday
});
```

**Manual**

```python
new TypeScriptComponent({
  ...,
  releaseTrigger: ReleaseTrigger.manual(),
});
```

### GitHub Credentials

For the release workflow to create tags, specific credentials are needed.
By default it expects a GitHub secret variable named `PROJEN_GITHUB_TOKEN` with
`read/write` access to `contents`. A separate token from the builtin `${{ secrets.GITHUB_TOKEN }}`
is needed in order to trigger the downstream `release-github` workflow.

This can be customized using the `projenCredentials` option.

**From a different secret**

```python
new TypeScriptComponent({
  ...,
  projenCredentials: GithubCredentials.fromPersonalAccessToken({ secret: 'MY_GITHUB_TOKEN' }),
});
```

**From a GitHub app**

```python
new TypeScriptComponent({
  ...,
  projenCredentials: GithubCredentials.fromApp({
    privateKeySecret: 'MY_GITHUB_APP_PRIVATE_KEY',
    appIdSecret: 'MY_GITHUB_APP_ID',
  }),
});
```

## Pulumi ESC setup for GitHub Actions

Use the `PulumiEscSetup` helper to add the [`pulumi/esc-action`](https://github.com/pulumi/esc-action) to generated workflows and control which secrets are exported. The helper keeps the step id stable (`esc`) so you can safely reference the action outputs from later steps.

### Option-to-input mapping

* `exportEnvironmentVariables` → `export-environment-variables`
* `version` → `version`
* `cloudUrl` → `cloud-url`
* `keys` (deprecated) → `keys` and automatically sets `export-environment-variables` to `true` for backward compatibility

### Examples

**Export specific mappings with passthrough**

```python
import { ExportEnvironmentVariables, PulumiEscSetup } from '@hallcor/pulumi-projen-project-types';

const esc = PulumiEscSetup.fromPersonalAccessToken({
  environment: 'acme/catalog/prod',
  exportEnvironmentVariables: ExportEnvironmentVariables.fromMapping([
    'AWS_ACCESS_KEY_ID',             // direct mapping
    'CD_TOKEN=DEPLOY_TOKEN',         // remap the ESC secret DEPLOY_TOKEN to CD_TOKEN
    '*',                             // passthrough any remaining secrets
  ]),
});

project.github?.addWorkflow('deploy').addJobs({
  deploy: {
    runsOn: ['ubuntu-latest'],
    steps: [
      { uses: 'actions/checkout@v4' },
      ...esc.setupSteps,
      { run: `echo "Deploy token is ${esc.output('CD_TOKEN')}"` },
    ],
  },
});
```

**Pin ESC CLI version and use a custom Pulumi Cloud URL**

```python
const esc = PulumiEscSetup.fromPersonalAccessToken({
  environment: 'acme/catalog/prod',
  version: '0.10.0',
  cloudUrl: 'https://api.enterprise.pulumi.com',
});
```

**Native OIDC authentication**

```python
import { JobPermission } from 'projen/lib/github/workflows-model';

const esc = PulumiEscSetup.fromOidcAuth({
  environment: 'acme/catalog/prod',
  organization: 'acme',
});

project.github?.addWorkflow('ci').addJobs({
  build: {
    permissions: { idToken: JobPermission.WRITE, contents: JobPermission.READ },
    runsOn: ['ubuntu-latest'],
    steps: [
      { uses: 'actions/checkout@v4' },
      ...esc.setupSteps,
      { run: 'echo "Pulumi token is available via esc outputs"' },
    ],
  },
});
```

> [!NOTE]
> ESC step outputs are available as `${{ steps.esc.outputs.<KEY> }}` or via `PulumiEscSetup.output('<KEY>')` when the helper is used. Existing workflows that still rely on the deprecated `keys` option continue to work, though new workflows should prefer `exportEnvironmentVariables` for fine-grained control.