How to Become A Programming Polyglot by One-language Effort
Tags: aws, iac, projen, cdk
Published: 2021-05-17 05:21:29

example Github repo: [https://github.com/HsiehShuJeng/projen-simple](https://github.com/HsiehShuJeng/projen-simple)  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6vswm172b0pc86c0qub.png "Required Secrets by Github Actions in order to Publish Construct Library in Maven, PyPI, npm, and NuGet") *Required Secrets by Github Actions in order to Publish Construct Library in Maven, PyPI, npm, and NuGet*
# Introduction  
[projen](https://github.com/projen/projen) is a tool for developers to manage their project configurations via code. It currently supports, well, by the time I was writing this blog post, 15 genres of projects. The one I felt the most interested in is building AWS CDK construct libraries for popular programming languages. Behind the scene that you can generate out a construct library for the languages such as C#, Go, Java, Python, and Typescript through a single project managed by projen is due to the power of [jsii](https://github.com/aws/jsii).
Simply put, you could regard jsii a technology that enables the AWS CDK to deliver polyglot libraries from a singe codebase. More simply, you could attempt to remember that by the jsii technology, you are empowered to write a library with one programming language such as Typescript and output the corresponding libraries in .NET, Go, Java, and Python.
I’ve been writing the AWS CDK using Typescript for few months. I chose it because it’s the origin. Don’t you ever hear the voice in your heart: ‘It’s time to back to the Motherland’? And the Tomorrowland is awesome, too. You agree?
Aight, back to the track. The AWS CDK has been assisting me in personal and company projects. Just way better than JSON and YAML. I have strong confidence I’ll be loyal to the CDK for sure instead of composing a CloudFormation template using yaml if there is no necessity.
Few weeks ago, I was invited by an AWS Developer Advocate to participate in a project called [cdk-cloudfront-plus](https://github.com/pahud/cdk-cloudfront-plus), and the project is managed by projen. Truly impressed with the tool. And finally I got some time the last weekend to dig into the tool, projen, a little bit.  
***  
# Preparation  
During the survey, I found out a Github repo maintained by Sebastian Hesse is especially helpful though the part for Java (Maven) has been kinda outdated. My goal is to output a library with the all supported programming languages in jsii. My familiarity to those languages is Python, Java, Typescript, Go, and C#. Since I still haven’t grasped the mechanism between Javascript and Go via jsii and `GOPATH`, i.e., haven’t figured out what naming and settings in the projen project can make the CI of Github Actions work therefore the Go package of the construct library. Considering time, I would just share the core part of how to output packages in 4 programming languages at the same time.  
## Initialize a `projen` project  
```bash
$ npx projen new awscdk-construct
$ alias pj='npx projen' // I moved it into ~/.bash_profile on my M1.
```  
## Figure out each projen command and arguments in `AwsCdkConstructLibrary`  
Though Sebastian said it probably takes you around 30 minutes to get along with `projen`, I actually spent few hours to make projen my friend. And publishing to **Central Maven** occupies most of the time. Hope the following content might save some time for you on the way to become a programming polyglot.  
## Build a construct library  
I searched articles in the AWS Blog with the first key appeared in my mind at the moment. And got this: ‘[*Introducing Amazon API Gateway service integration for AWS Step Functions*](https://aws.amazon.com/tw/blogs/compute/introducing-amazon-api-gateway-service-integration-for-aws-step-functions/)’. I CDK-ified the first example combined with a state machine and an API Gateway Rest API and published it to 4 language repositories with `projen`.  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8nmztojrzvduqtwjz637.png) *State Machine Diagram Generated by CDK Example*  
***  
# Publishing to supported language repositories    
## How to publish a package in `npm`?  
### Arguments in the `.projenrc.js` you need to give attention to 
* `releaseBranches`: branches which trigger a release.  
* `releaseToNpm`: automatically release to npm when new versions are introduced.  
* `releaseWorkflow`: define a GitHub workflow for releasing from “main” when new versions are bumped.  
* `releaseEveryCommit`: automatically release new versions every commit to one of branches in releaseBranches.   
```typescript
new AwsCdkConstructLibrary({
   .
   .
   .
    releaseToNpm: true,
    releaseBranches: ['main'],
    releaseWorkflow: true,
    releaseEveryCommit: true
   .
   .
   .
   })
```
### required information by Github Actions  
* `NPM_TOKEN`: it is required by Github Actions to publish the `npm` package.   

After executing `npx projen` (you could consider making it as an alias such as `pj`), you’ll notice in the `release.yml` under `.github/workflows`
that `NPM_TOKEN` is required by Github Actions to publish the `npm` package. If you’re just an `npm` newbie as me, don’t panic! Be strong, be calm. The following steps are what you need to go through:  
1. create an `npm` account (email validation is required)  
2. create an access token on the web page of your npm account 
   Choose the type of AUTOMATION when you’re about to create the access token. AUTOMATION! AUTOMATION! AUTOMATION TYPE! It’s important to be emphasized three times.  
3. store the access token as [an Actions secret](https://docs.github.com/en/actions/reference/encrypted-secrets) in your Github repository.  

If you go everything smoothly, you get an email whose content will be similar to the following picture. And you can find out published `npm` packages at the npm pool as [here](https://www.npmjs.com/package/projen-statemachine-example).  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u8bscpwjw50k22xwf817.jpg) *Email Message after Publishing an npm package via projen with success*    

## How to publish a package to **PyPi**?  
### Arguments in `.projenrc.js` you need to give attention to  
* `publishToPypi`  
You gotta set a distribution name and a module name for the Python package.  
```typescript
publishToPypi: {    
    distName: 'scotthsieh_projen_statemachine',
    module: 'scotthsieh_projen_statemachine'  
}
```
### Required information by Github Actions  
* `TWINE_USERNAME`  
* `TWINE_PASSWORD`   

If you read the content related to publishing an `npm` package above, you’ll be very clear that those environment variables are required by what service. With proper settings in the  `.projenrc.js` , you’ll find an entry `release_pypi` in the `release.yml` under `.github/workflows`.  

`TWINE_USERNAME` and `TWINE_PASSWORD` is your **PyPi** account information. And your **PyPi account needs to be verified**.  

With a green check symbol given by **Github Actions**, you can see your package (project) in your **PyPI** account which means you could find out the Python package by the name you've declared in the projen project in the **PyPI** pool.  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kwbmo19jrwds69gzpebj.png) *Python Package in Your PyPI Account after a Successful CICD by Github Actions.*  

## How to publish a package to **Maven**?  
### Arguments in the .projenrc.js you need to give attention to  
* `publishToMaven`  
You need to declare `groupId`, `artifactId`, and `package` as you always do in managing a Java application project by Maven except version information in this construct library project based on projen. The default Maven endpoint in the `.projenrc.js` is [https://oss.sonatype.org](https://oss.sonatype.org). Due to the policy executed by Sonatype, you need to tweak it as [https://s01.oss.sonatype.org](https://s01.oss.sonatype.org) in the `.projenrc.js` for those who create their Sonatype **JIRA** accounts after February, 2021.  
```typescript
publishToMaven: {
    mavenGroupId: 'io.github.hsiehshujeng',
    mavenArtifactId: 'projen-inception',
    javaPackage: 'io.github.hsiehshujeng.projen.inception',
    mavenEndpoint: 'https://s01.oss.sonatype.org' // check https://central.sonatype.org/publish/release/#login-into-ossrh
},
```
### Few more steps for Maven  
1. Create an account for Maven central  
   You need to create an account for Maven central via **OSSRH**. Two short films [in the guide](https://central.sonatype.org/publish/publish-guide/) will be helpful. You could choose a domain as `groupId` e.g. org.example, for the account, or your Github name as groupId , e.g. `io.github.${GITHUB_USERNAME}`. (`com.github` has no long been supported as a valid groupId since Apr. 1st, 2021 and the detail can be looked up here)  

    After you create a **JIRA** issue in the Sonatype **JIRA** tracking system, you’ll get response within sometime. Take me for example, it’s only a 4-minute waiting after I created the **JIRA** issue. You only need to respond accordingly from their robotic response.
Within this exploration for projen, my account for Maven is connected to the JIRA issue [OSSRH-68981](https://issues.sonatype.org/browse/OSSRH-68981).
2. Create a GPG key  
   How to generate the GPG key for my `projen` project to produce the Java library? You could refer to ‘*How to create a GPG key*?’ at the section of Maven in [jsii-release](https://github.com/cdklabs/jsii-release#maven). During the generating progress of the GPG key, you will be asked to enter a passphrase for the key. Please memorize the passphrase of the GPG key in any way like it’s your lifetime partner, promise me, since you’ll need it for an Actions secret and exporting the private key.  
Some information you might find it useful.  

    * consider executing `$ gpg --full-generate-key` and choose **RSA** with the length of 4,096.  
    * you’ll need to paste the public key onto [https://keyserver.ubuntu.com/](https://keyserver.ubuntu.com/).  

After executing `npx projen` (you could consider making it as an alias such as `pj`), you should find the entry named release_maven in the `release.yml` under `.github/workflows`.  

### Required information by Github Actions  
* `MAVEN_GPG_PRIVATE_KEY`: execute `echo $(cat -e private.pem) | sed 's/\$/\\n\g' | sed 's/\$$//'` then past the one-line content to this Actions secret.
* `MAVEN_GPG_PRIVATE_KEY_PASSPHRASE`: the passphrase you entered during the generating progress of the GPG key.
* `MAVEN_USERNAME`: the user name you take to log-in the Sonatype JIRA tracking system.
* `MAVEN_PASSWORD`: the password you take to log-in the Sonatype JIRA tracking system.
* `MAVEN_STAGING_PROFILE_ID`, an identity shown up on the URL of Staging Profile after logging in [https://s01.oss.sonatype.org/](https://s01.oss.sonatype.org/).  

If you go smoothly, you should be able to find the Java package similar to [this](https://s01.oss.sonatype.org/#nexus-search;quick~io.github.hsiehshujeng).  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m85xg00ov0uxztufsmar.png) *Java Package Searched with io.github.hsiehshujeng after a Successful CICD by Github Actions.*  

When the tunnel to the **Central Maven** is open after you upload an artifact into the **Nexus Repository Manager** with success, you should be able to search your published Java package at https://search.maven.org.  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rftdvpf1qkax4uftyy39.png) *Search Result at Maven Central Repository Search*  

## How to publish a package to Nuget?  
### Arguments in the .projenrc.js you need to give attention to  
* `publishToNuget`  
Just follow the naming rules of NuGet packages.  
```typescript
publishToNuget: {
    dotNetNamespace: 'ScottHsieh.Examples',
    packageId: 'Projen.Inception',
},
```
By executing `npx projen` with proper command (you could consider making it as an alias such as `pj`), you are able to get the entry named `release_nuget` in the `release.yml` under `.github/workflows`.  
### required information by Github Actions  
* `NUGET_API_KEY`: a token that enables your project to deploy a NuGet package  
With a while after the CI in **Github Actions** is over, you should get an email similar to the following picture and can search your **NuGet** package as here in the **NuGet** Gallery.  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txngx5pag29pv2f5r4oy.jpg) *Received Email Message after Publishing a NuGet package via projen with success*  

# Conclusion  
If all things go done well, you should see the following diagram in your Github repository.   
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dgs66jq229qoamys23m.png) *Packages Output to Supported Language Repositories with Success*  

By confirming the custom AWS construct has been published to the corresponding language pools, you could start deploying a stack with the construct through a programming language you prefer.  
* how to deploy with Typescript: refer to [here](https://github.com/HsiehShuJeng/projen-simple/tree/main/src/demo/typescript)  
* how to deploy with Python: refer to [here](https://github.com/HsiehShuJeng/projen-simple/tree/main/src/demo/python)  
* how to deploy with Java: refer to [here](https://github.com/HsiehShuJeng/projen-simple/tree/main/src/demo/java) 
* how to deploy with Csharp: refer to [here](https://github.com/HsiehShuJeng/projen-simple/tree/main/src/demo/csharp)    
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qt0vu8y96mnxf0k27agk.png) *A Glimpse of Successful Deployments via Different Programming Languages*  

If you wanna see the reality of this post by accident, please go to this [repo](https://github.com/HsiehShuJeng/projen-simple) maintained by me. May the code be with you. See you next time. ^.<  

***  

# References  
1. Ben-Israel, E., 2021. *PROJECT STRUCTURE*. [online] Cdkworkshop.com. Available at: <https://cdkworkshop.com/40-dotnet/20-create-project/300-structure.html> [Accessed 18 May 2021].
2. Bui-Palsulich, T., 2019. *Publishing Go Modules — The Go Blog*. [online] Blog.golang.org. Available at: <https://blog.golang.org/publishing-go-modules> [Accessed 15 May 2021].  
3. Central.sonatype.org. 2021. *Central Repository Changelog — The Central Repository Documentation*. [online] Available at: <https://central.sonatype.org/changelog/#2021-04-01-comgithub-is-not-supported-anymore-as-a-valid-coordinate> [Accessed 15 May 2021].  
4. Central.sonatype.org. 2021. *OSSRH Guide — The Central Repository Documentation*. [online] Available at: <https://central.sonatype.org/publish/publish-guide/#deployment> [Accessed 15 May 2021].  
5. Docs.github.com. 2021. *Encrypted secrets — GitHub Docs*. [online] Available at: <https://docs.github.com/en/actions/reference/encrypted-secrets> [Accessed 15 May 2021].  
6. Docs.npmjs.com. 2021. *About access tokens | npm Docs*. [online] Available at: <https://docs.npmjs.com/about-access-tokens> [Accessed 15 May 2021].  
7. Hesse, S., 2021. *Migrating a CDK Construct to projen and jsii* . [online] Sebastian Hesse — Software Engineer. Available at: <https://www.sebastianhesse.de/2021/03/01/migrating-a-cdk-construct-to-projen-and-jsii/> [Accessed 15 May 2021].  
8. Jones, M., 2019. *Scoped API keys*. [online] Docs.microsoft.com. Available at: <https://docs.microsoft.com/en-us/nuget/nuget-org/scoped-api-keys> [Accessed 16 May 2021].  
9. Sonatype, Inc., 2021. *OSSRH Guide — The Central Repository Documentation*. [online] Central.sonatype.org. Available at: <https://central.sonatype.org/publish/publish-guide/> [Accessed 15 May 2021].  
10. The Apache Software Foundation, 2021. *Maven — Guide to uploading artifacts to the Central Repository*. [online] Maven.apache.org. Available at: <https://maven.apache.org/repository/guide-central-repository-upload.html> [Accessed 15 May 2021].  
11. seeebiii, 2021. *Create and Publish CDK Constructs Using projen and jsii*. [online] GitHub. Available at: <https://github.com/seeebiii/projen-test> [Accessed 15 May 2021].