-
Notifications
You must be signed in to change notification settings - Fork 880
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
439 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.nx/cache | ||
generated-website | ||
dist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
# Nx Monorepo | ||
|
||
This example shows how to use Nx to organize a mono repo and track dependencies. | ||
|
||
The example consists of the following components: | ||
|
||
``` | ||
- packages: | ||
- s3folder: ComponentResource that manages a S3 bucket | ||
- website-deploy: ComponentResource resource that manages files in a S3 bucket | ||
- website-builder: Mock website generator that creates HTML output | ||
- infra: Pulumi program that uses the s3folder and website ComponentResources to deploy a website | ||
``` | ||
|
||
To deploy the latest version of the website, we need to respect the certain dependencies: | ||
|
||
- website-builder needs to be compiled before we can use it to generate the HTML output. | ||
- s3folder and website-deploy need to be compiled before we can build infra. | ||
- We need to generate HTML output before we can deploy the infra. | ||
- infra needs to be compiled before we can deploy. | ||
|
||
These dependecies can be defined using Nx, for example in [infra/package.json](./infra//package.json) we declare that the `deploy` needs its dependencies to be built, and the HTML to generated: | ||
|
||
``` | ||
... | ||
"nx": { | ||
"targets": { | ||
"deploy": { | ||
"dependsOn": [ | ||
"build", | ||
"website-builder:generate" | ||
] | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Nx can visualize the dependencies for us using `npx nx deploy infra --graph` | ||
|
||
![Dependency Graph](./dependency-graph.png) | ||
|
||
## Deploying | ||
|
||
### Prerequisites | ||
|
||
1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/) | ||
2. [Configure AWS Credentials](https://www.pulumi.com/docs/intro/cloud-providers/aws/setup/) | ||
|
||
### Steps | ||
|
||
Since Nx manages the interdependencies, all we have to do is to install our node dependencies | ||
|
||
```bash | ||
npm install | ||
``` | ||
|
||
and then run nx: | ||
|
||
```bash | ||
npx nx deploy infra | ||
``` | ||
|
||
``` | ||
✔ 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 | ||
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— | ||
> nx run infra:build | ||
> [email protected] build | ||
> tsc | ||
> nx run infra:deploy | ||
> [email protected] deploy | ||
> pulumi up --stack dev | ||
The stack 'dev' does not exist. | ||
If you would like to create this stack now, please press <ENTER>, otherwise press ^C: | ||
Created stack 'dev' | ||
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<string> | ||
Resources: | ||
+ 7 to create | ||
Do you want to perform this update? yes | ||
Updating (dev) | ||
View in Browser (Ctrl+O): https://app.pulumi.com/julienp/nx-monorepo/dev/updates/1 | ||
Type Name Status | ||
+ pulumi:pulumi:Stack nx-monorepo-dev created (6s) | ||
+ ├─ pulumi:examples:S3Folder my-folder created (5s) | ||
+ │ ├─ aws:s3:Bucket my-folder created (1s) | ||
+ │ ├─ aws:s3:BucketPublicAccessBlock public-access-block created (0.76s) | ||
+ │ └─ aws:s3:BucketPolicy bucketPolicy created (0.85s) | ||
+ └─ pulumi:examples:WebsiteDeploy my-website created (2s) | ||
+ └─ aws:s3:BucketObject index.html created (0.80s) | ||
Outputs: | ||
websiteUrl: "my-folder-a64ab3c.s3-website.eu-central-1.amazonaws.com" | ||
Resources: | ||
+ 7 created | ||
Duration: 9s | ||
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— | ||
NX Successfully ran target deploy for project infra and 5 tasks it depends on (42s) | ||
``` | ||
|
||
To destroy the stack, we run: | ||
|
||
``` | ||
npx nx destroy infra | ||
``` | ||
|
||
``` | ||
> nx run infra:destroy | ||
> [email protected] destroy | ||
> pulumi destroy --stack dev | ||
Previewing destroy (dev) | ||
View in Browser (Ctrl+O): https://app.pulumi.com/julienp/nx-monorepo/dev/previews/b640cce7-a9df-49a5-b004-3fbdbe65c4eb | ||
Type Name Plan | ||
- pulumi:pulumi:Stack nx-monorepo-dev delete | ||
- ├─ pulumi:examples:S3Folder my-folder delete | ||
- │ ├─ aws:s3:BucketPolicy bucketPolicy delete | ||
- │ ├─ aws:s3:BucketPublicAccessBlock public-access-block delete | ||
- │ └─ aws:s3:Bucket my-folder delete | ||
- └─ pulumi:examples:WebsiteDeploy my-website delete | ||
- └─ aws:s3:BucketObject index.html delete | ||
Outputs: | ||
- websiteUrl: "my-folder-a64ab3c.s3-website.eu-central-1.amazonaws.com" | ||
Resources: | ||
- 7 to delete | ||
Do you want to perform this destroy? yes | ||
Destroying (dev) | ||
View in Browser (Ctrl+O): https://app.pulumi.com/julienp/nx-monorepo/dev/updates/2 | ||
Type Name Status | ||
- pulumi:pulumi:Stack nx-monorepo-dev deleted (0.31s) | ||
- ├─ pulumi:examples:WebsiteDeploy my-website deleted (0.60s) | ||
- │ └─ aws:s3:BucketObject index.html deleted (0.88s) | ||
- └─ pulumi:examples:S3Folder my-folder deleted (0.82s) | ||
- ├─ aws:s3:BucketPolicy bucketPolicy deleted (0.96s) | ||
- ├─ aws:s3:BucketPublicAccessBlock public-access-block deleted (0.91s) | ||
- └─ aws:s3:Bucket my-folder deleted (0.74s) | ||
Outputs: | ||
- websiteUrl: "my-folder-a64ab3c.s3-website.eu-central-1.amazonaws.com" | ||
Resources: | ||
- 7 deleted | ||
Duration: 7s | ||
The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained. | ||
If you want to remove the stack completely, run `pulumi stack rm dev`. | ||
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— | ||
NX Successfully ran target destroy for project infra (18s) | ||
``` |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
name: nx-monorepo | ||
description: A project using an Nx monorepo. | ||
main: dist/index.js | ||
runtime: | ||
name: nodejs | ||
options: | ||
typescript: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import * as path from "path" | ||
import * as s3folder from "s3folder" | ||
import * as websiteDeploy from "website-deploy" | ||
|
||
// Create the folder to hold our website files | ||
const folder = new s3folder.S3Folder("my-folder", {}) | ||
export const websiteUrl = folder.websiteUrl | ||
|
||
// Deploy the website to the folder | ||
const generatedWebsite = path.join("..", "..", "generated-website") | ||
const website = new websiteDeploy.WebsiteDeploy("my-website", folder.bucket, generatedWebsite, {}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"name": "infra", | ||
"main": "dist/index.js", | ||
"version": "1.0.0", | ||
"dependencies": { | ||
"@pulumi/pulumi": "latest", | ||
"s3folder": "*", | ||
"website-deploy": "*", | ||
"website-builder": "*" | ||
}, | ||
"scripts": { | ||
"build": "tsc", | ||
"deploy": "pulumi up --stack dev", | ||
"destroy": "pulumi destroy --stack dev" | ||
}, | ||
"nx": { | ||
"targets": { | ||
"deploy": { | ||
"dependsOn": [ | ||
"build", | ||
"website-builder:generate" | ||
] | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"extends": "../tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "dist" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"extends": "nx/presets/npm.json", | ||
"$schema": "./node_modules/nx/schemas/nx-schema.json", | ||
"targetDefaults": { | ||
"build": { | ||
"cache": true, | ||
"dependsOn": [ | ||
"^build" | ||
] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "nx-repo", | ||
"version": "1.0.0", | ||
"scripts": {}, | ||
"private": true, | ||
"devDependencies": { | ||
"@nx/js": "18.0.5", | ||
"nx": "18.0.5", | ||
"typescript": "^5.3.3" | ||
}, | ||
"workspaces": [ | ||
"packages/*", | ||
"infra" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import * as aws from "@pulumi/aws"; | ||
import * as pulumi from "@pulumi/pulumi"; | ||
|
||
export class S3Folder extends pulumi.ComponentResource { | ||
readonly bucket: pulumi.Output<aws.s3.Bucket>; | ||
readonly websiteUrl: pulumi.Output<string>; | ||
|
||
constructor(bucketName: string, opts: pulumi.ComponentResourceOptions) { | ||
super("pulumi:examples:S3Folder", bucketName, {}, opts); | ||
|
||
// Create a bucket and expose a website index document | ||
let siteBucket = new aws.s3.Bucket(bucketName, { | ||
website: { | ||
indexDocument: "index.html", | ||
}, | ||
}, { parent: this }); // specify resource parent | ||
|
||
const publicAccessBlock = new aws.s3.BucketPublicAccessBlock("public-access-block", { | ||
bucket: siteBucket.id, | ||
blockPublicAcls: false, | ||
}, { parent: this }); | ||
|
||
// Set the access policy for the bucket so all objects are readable | ||
let bucketPolicy = new aws.s3.BucketPolicy("bucketPolicy", { | ||
bucket: siteBucket.bucket, | ||
policy: siteBucket.bucket.apply(this.publicReadPolicyForBucket), | ||
}, { parent: this, dependsOn: publicAccessBlock }); // specify resource parent | ||
|
||
this.bucket = pulumi.output(siteBucket); | ||
this.websiteUrl = siteBucket.websiteEndpoint; | ||
|
||
// Register output properties for this component | ||
this.registerOutputs({ | ||
bucket: this.bucket, | ||
websiteUrl: this.websiteUrl, | ||
}); | ||
} | ||
|
||
publicReadPolicyForBucket(bucketName: string) { | ||
return JSON.stringify({ | ||
Version: "2012-10-17", | ||
Statement: [{ | ||
Effect: "Allow", | ||
Principal: "*", | ||
Action: [ | ||
"s3:GetObject" | ||
], | ||
Resource: [ | ||
`arn:aws:s3:::${bucketName}/*` | ||
] | ||
}] | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"name": "s3folder", | ||
"main": "dist/index.js", | ||
"version": "1.0.0", | ||
"dependencies": { | ||
"@pulumi/pulumi": "^3.107.0", | ||
"@pulumi/aws": "^6.23.0" | ||
}, | ||
"scripts": { | ||
"build": "tsc" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "dist" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
import * as fs from 'fs'; | ||
import * as path from "path"; | ||
|
||
const outDir = path.join("..", "..", "generated-website"); | ||
const indexPath = path.join(outDir, "index.html") | ||
|
||
fs.mkdirSync(outDir, { recursive: true }) | ||
fs.writeFileSync(indexPath, `Hello, world! ${new Date().toISOString()}`) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "website-builder", | ||
"main": "dist/index.js", | ||
"version": "1.0.0", | ||
"dependencies": {}, | ||
"scripts": { | ||
"build": "tsc", | ||
"generate": "node ./dist/index.js" | ||
}, | ||
"nx": { | ||
"targets": { | ||
"generate": { | ||
"outputs": [ | ||
"{workspaceRoot}/generated-website" | ||
], | ||
"dependsOn": [ | ||
"website-builder:build" | ||
] | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.