<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0"><channel><title>Pulumi Blog: Nx</title><link>https://www.pulumi.com/blog/tag/nx/</link><description>Pulumi blog posts: Nx.</description><language>en-us</language><pubDate>Tue, 26 Mar 2024 17:19:00 +0100</pubDate><item><title>Using Pulumi Inside Node.js Monorepos</title><link>https://www.pulumi.com/blog/nx-monorepo/</link><pubDate>Tue, 26 Mar 2024 17:19:00 +0100</pubDate><guid>https://www.pulumi.com/blog/nx-monorepo/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/nx-monorepo/index.png" /&gt;
&lt;p&gt;One of Pulumi&amp;rsquo;s core goals is to provide cloud engineers with access to the very best software engineering tooling available. Using traditional programming languages like Node.js, Python, Go, .NET and Java means the latest and greatest software engineering tools from each of these ecosystems is available to bring to bear on managing cloud infrastructure, natively integrated with your existing development environments.&lt;/p&gt;
&lt;p&gt;In the Node.js ecosystem, we&amp;rsquo;ve seen an explosion of great tooling over the last couple of years around support for monorepos - larger repositories built out of many smaller projects, and sharing code and dependencies smartly across all the various projects. We&amp;rsquo;ve seen many of our Pulumi Node.js users adopting these tools and repo structures, including tools like &lt;a href="https://yarnpkg.com/features/workspaces"&gt;Yarn Workspaces&lt;/a&gt;, &lt;a href="https://pnpm.io/"&gt;pnpm&lt;/a&gt;, &lt;a href="https://turbo.build/"&gt;Turborepo&lt;/a&gt;, and especially &lt;a href="https://nx.dev"&gt;Nx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While it has always been possible to apply these tools to Pulumi Node.js projects in TypeScript or JavaScript just like any other Node.js project, we&amp;rsquo;ve recently made &lt;a href="https://github.com/pulumi/pulumi/issues/15436"&gt;a&lt;/a&gt; &lt;a href="https://github.com/pulumi/pulumi/issues/2661"&gt;number&lt;/a&gt; &lt;a href="https://github.com/pulumi/pulumi/issues/7168"&gt;of&lt;/a&gt; &lt;a href="https://github.com/pulumi/pulumi/issues/3013"&gt;enhancements&lt;/a&gt; &lt;a href="https://github.com/pulumi/pulumi/issues/15455"&gt;and&lt;/a&gt; &lt;a href="https://github.com/pulumi/examples/issues/1605"&gt;fixes&lt;/a&gt; to make sure that Pulumi works truly seamlessly with these tools.&lt;/p&gt;
&lt;p&gt;In this post, we&amp;rsquo;ll show how you can build a seamless development workflow by integrating Pulumi code level abstractions, such as &lt;a href="https://www.pulumi.com/docs/concepts/resources/components/"&gt;Component Resources&lt;/a&gt;, with a monorepo-based build system like &lt;a href="https://nx.dev"&gt;Nx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Component resources let us create reusable components that manage logical groupings of resources. With modern monorepo tooling, and our recent improvements to make Pulumi aware of monorepo setups, we can colocate these reusable components, Pulumi infrastructure programs, and application code all in one monorepo, and have Nx manage the build and deploy-time dependencies for us.&lt;/p&gt;
&lt;p&gt;We will walk through an example project that deploys a website built with &lt;a href="https://astro.build"&gt;Astro&lt;/a&gt; to AWS S3. The complete code can be found at &lt;a href="https://github.com/pulumi/examples/tree/master/nx-monorepo"&gt;pulumi/examples/nx-monorepo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Our example monorepo has the following structure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pulumi/examples/tree/master/nx-monorepo/website"&gt;website&lt;/a&gt;: A website built with &lt;a href="https://astro.build"&gt;Astro&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pulumi/examples/blob/master/nx-monorepo/components/s3folder/index.ts"&gt;components/s3folder&lt;/a&gt;: A component resource that manages a S3 bucket and its access policies.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pulumi/examples/blob/master/nx-monorepo/components/website-deploy/index.ts"&gt;components/website-deploy&lt;/a&gt;: A component resource resource that manages files in a S3 bucket&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pulumi/examples/blob/master/nx-monorepo/infra/index.ts"&gt;infra&lt;/a&gt;: A Pulumi program that uses the &lt;code&gt;s3folder&lt;/code&gt; and &lt;code&gt;website-deploy&lt;/code&gt; component resources to deploy the generated &lt;code&gt;website&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By using &lt;a href="https://docs.npmjs.com/cli/v10/using-npm/workspaces"&gt;npm workspaces&lt;/a&gt; we can have multiple npm packages managed from a singular top-level package. Npm will take care of installing the dependencies for all our packages and enables packages within the monorepo to reference each other. In the &lt;a href="https://github.com/pulumi/examples/blob/master/nx-monorepo/package.json"&gt;package.json&lt;/a&gt; at the root of the monorepo we set up the workspaces matching our folder structure. &lt;a href="https://classic.yarnpkg.com/lang/en/docs/workspaces/"&gt;Yarn workspaces&lt;/a&gt; work similarly and are fully supported by Pulumi.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// package.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;workspaces&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;components/*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;infra&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;website&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="typescript"&gt;TypeScript&lt;/h2&gt;
&lt;p&gt;Pulumi has builtin TypeScript support and compiles your code on the fly without manual build-step, however this is currently limited to TypeScript 3.8. We are working on providing more choice here, but in the mean time Nx makes it easy to add a build-step to compile code using any version of TypeScript. For this example we are using the latest and greatest, TypeScript 5.4.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;As of &lt;a href="https://www.npmjs.com/package/@pulumi/pulumi"&gt;v3.113.0 of the @pulumi/pulumi NPM package&lt;/a&gt; any version of TypeScript is supported natively. To select the version to use, add it as a &lt;a href="https://www.pulumi.com/docs/languages-sdks/javascript/#typescript-versions"&gt;dependency to your package.json&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="declaring-dependencies"&gt;Declaring Dependencies&lt;/h2&gt;
&lt;p&gt;If we were to manually build and deploy the code in our monorepo, we would have to run the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;astro build&lt;/code&gt; to generate the HTML output that we want to deploy.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npm run build&lt;/code&gt; for &lt;code&gt;s3folder&lt;/code&gt; and &lt;code&gt;website-deploy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npm run build&lt;/code&gt; for &lt;code&gt;infra&lt;/code&gt; afterwards, since this imports &lt;code&gt;s3folder&lt;/code&gt; and &lt;code&gt;website-deploy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;pulumi up&lt;/code&gt; to deploy our website.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Instead of running these steps manually, we will leverage Nx&amp;rsquo;s task running mechanism, which can be made aware of the dependencies between the packages in the monorepo. This ensures we don&amp;rsquo;t accidentally forget a step. On top of that, Nx provides caching, so we also avoid re-running unnecessary tasks on subsequent runs.&lt;/p&gt;
&lt;p&gt;Because we are using npm workspaces, Nx can understand the dependencies declared in the &lt;code&gt;package.json&lt;/code&gt; for each of the packages in our monorepo. For example in &lt;a href="https://github.com/pulumi/examples/blob/master/nx-monorepo/infra/package.json"&gt;infra/package.json&lt;/a&gt; we declare that we depend on &lt;code&gt;s3folder&lt;/code&gt;, &lt;code&gt;website&lt;/code&gt; and &lt;code&gt;website-deploy&lt;/code&gt;.
We also let Nx know that the &lt;code&gt;deploy&lt;/code&gt; target in the &lt;code&gt;infra&lt;/code&gt; package depends on the build step, and the HTML generation step of the &lt;code&gt;website&lt;/code&gt; package:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// infra/package.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;infra&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dependencies&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;latest&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;s3folder&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;website-deploy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;website&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;build&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tsc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;deploy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;pulumi up --stack dev&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;nx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;targets&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;deploy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;cache&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dependsOn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;build&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;website:generate&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In &lt;a href="https://github.com/pulumi/examples/blob/master/nx-monorepo/nx.json"&gt;nx.json&lt;/a&gt; we let Nx know that each package&amp;rsquo;s build-step depends on its dependencies&amp;rsquo; build-steps. With that Nx now knows that in order build &lt;code&gt;infra&lt;/code&gt;, it first needs to build its dependencies.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// nx.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;extends&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nx/presets/npm.json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;$schema&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./node_modules/nx/schemas/nx-schema.json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;targetDefaults&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;build&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;cache&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dependsOn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^build&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The full dependency graph, as understood by Nx, can be visualized by running &lt;code&gt;npx nx deploy infra --graph&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.pulumi.com/blog/nx-monorepo/dependency-graph.png" alt="Dependency graph of our monorepo example"&gt;&lt;/p&gt;
&lt;h2 id="walkthrough"&gt;Walkthrough&lt;/h2&gt;
&lt;p&gt;Now that we have taught Nx all about the dependencies in our monorepo, we can run &lt;code&gt;npx nx deploy infra&lt;/code&gt; and Nx will run all the required steps in the correct order, using parallelism where possible.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; ✔ 4/4 dependent project tasks succeeded [0 read from cache]
Hint: you can run the command with --verbose to see the full dependent project outputs
————————————————————————————————————————————————————————————————————————————————
&amp;gt; nx run infra:build
&amp;gt; infra@1.0.0 build
&amp;gt; tsc
&amp;gt; nx run infra:deploy
&amp;gt; infra@1.0.0 deploy
&amp;gt; pulumi up --stack dev
The stack &amp;#39;dev&amp;#39; does not exist.
If you would like to create this stack now, please press &amp;lt;ENTER&amp;gt;, otherwise press ^C:
Created stack &amp;#39;dev&amp;#39;
Previewing update (dev)
View in Browser (Ctrl+O): https://app.pulumi.com/julienp/nx-monorepo/dev/previews/fc7630fd-7dc4-4c7e-baa0-3d6e014fc90a
Type Name Plan
+ pulumi:pulumi:Stack nx-monorepo-dev create
+ ├─ pulumi:examples:WebsiteDeploy my-website create
+ │ └─ aws:s3:BucketObject index.html create
+ └─ pulumi:examples:S3Folder my-folder create
+ ├─ aws:s3:Bucket my-folder create
+ ├─ aws:s3:BucketPublicAccessBlock public-access-block create
+ └─ aws:s3:BucketPolicy bucketPolicy create
Outputs:
websiteUrl: output&amp;lt;string&amp;gt;
Resources:
+ 7 to create
Do you want to perform this update? yes
Updating (dev)
...
NX Successfully ran target deploy for project infra and 4 tasks it depends on (27s)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The output tells us that Nx found the 4 dependent tasks for the &lt;code&gt;deploy&lt;/code&gt; task of the &lt;code&gt;infra&lt;/code&gt; package and ran them successfully.&lt;/p&gt;
&lt;p&gt;If we now run &lt;code&gt;npx nx deploy infra&lt;/code&gt; again, we can see Nx&amp;rsquo;s caching mechanism in action. Nx notices that there are no code changes to the &lt;code&gt;infra&lt;/code&gt; package, and that none of its dependencies have changed either, so it just replays the output from the previous run.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; ✔ 3/3 dependent project tasks succeeded [3 read from cache]
Hint: you can run the command with --verbose to see the full dependent project outputs
————————————————————————————————————————————————————————————————————————————————
&amp;gt;nx run infra:build [existing outputs match the cache, left as is]
&amp;gt; infra@1.0.0 build
&amp;gt; tsc
&amp;gt; nx run infra:deploy [existing outputs match the cache, left as is]
&amp;gt; infra@1.0.0 deploy
&amp;gt; pulumi up --stack dev
Previewing update (dev)
...
NX Successfully ran target deploy for project infra and 4 tasks it depends on (29ms)
Nx read the output from the cache instead of running the command for 5 out of 5 tasks.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let&amp;rsquo;s create a new page in our website by adding a markdown file in the &lt;code&gt;src/pages&lt;/code&gt; folder.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt; &amp;gt; website/src/pages/hello.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When we run &lt;code&gt;npx nx deploy infra&lt;/code&gt; again, Nx notices that there is a change to the website and reruns the HTML generation step. Since one of the dependencies of &lt;code&gt;infra&lt;/code&gt; has now changed, the stack is re-deployed.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; ✔ 2/2 dependent project tasks succeeded [2 read from cache]
Hint: you can run the command with --verbose to see the full dependent project outputs
————————————————————————————————————————————————————————————————————————————————
&amp;gt; nx run infra:build
&amp;gt; infra@1.0.0 build
&amp;gt; tsc
&amp;gt; nx run infra:deploy
&amp;gt; infra@1.0.0 deploy
&amp;gt; pulumi up --stack dev
Previewing update (dev)
View in Browser (Ctrl+O): https://app.pulumi.com/v-julien-pulumi-corp/nx-monorepo/dev/previews/8d9db825-77e1-4d1a-8f9b-8279481e7e40
Type Name Plan
pulumi:pulumi:Stack nx-monorepo-dev
└─ pulumi:examples:WebsiteDeploy my-website
+ └─ aws:s3:BucketObject hello/index.html create
Resources:
+ 1 to create
8 unchanged
Do you want to perform this update? yes
Updating (dev)
...
NX Successfully ran target deploy for project infra and 4 tasks it depends on (19s)
Nx read the output from the cache instead of running the command for 2 out of 5 tasks.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can see that Nx used the cached results for 2 of our tasks, &lt;code&gt;s3folder&lt;/code&gt; and &lt;code&gt;website-deploy&lt;/code&gt; didn&amp;rsquo;t change, so Nx skips rebuilding them. Nx also ran the other 3 tasks to generate the website&amp;rsquo;s HTML, building the infra package and finally deploying the infra package.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Ship infrastructure from your monorepo&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Colocate reusable Pulumi component resources, infrastructure programs, and application code in one monorepo, then build and deploy them together with Nx. Manage every stack in Pulumi Cloud.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post we&amp;rsquo;ve shown how we can combine Pulumi&amp;rsquo;s code level abstractions with a build system to create a seamless developer workflow. By using a monorepo we can colocate our reusable components with the Pulumi programs that use the components, as well as our application code. Tools like Nx allow us to intelligently manage the dependencies between the packages in the monorepo, ensuring we are always deploying the correct version of the code.&lt;/p&gt;
&lt;p&gt;Pulumi provides you with access to the latest and greatest software engineering tools (like Nx), and allows you to bring them to bear on managing cloud infrastructure, natively integrated with your existing development environments.&lt;/p&gt;</description><author>Julien Poissonnier</author><category>development-environment</category><category>monorepo</category><category>nx</category></item></channel></rss>