|
1 |
| -# Decay |
| 1 | +<p align="center"><br><img src="./icon.png" width="128" height="128" alt="Turbo engine" /></p> |
| 2 | +<h2 align="center">Turbo Cache Server</h2> |
| 3 | +<p align="center"> |
| 4 | + <a href="https://turbo.build/repo">Turborepo</a> remote cache server as a Github Action with S3-compatible storage support. |
| 5 | +</p> |
2 | 6 |
|
3 |
| -[Turborepo](https://turbo.build/repo) remote cache server with S3-compatible storage |
| 7 | +### How can I use this in my monorepo? |
| 8 | + |
| 9 | +You can use the Turbo Cache Server as **Github Action**. Here is how: |
| 10 | + |
| 11 | +1. On your workflow files, add the following global environment variables: |
| 12 | + |
| 13 | +```yml |
| 14 | +env: |
| 15 | + TURBO_API: 'http://127.0.0.1:8585' |
| 16 | + TURBO_TEAM: 'NAME_OF_YOUR_REPO_HERE' |
| 17 | + TURBO_TOKEN: 'turbo-token' |
| 18 | +``` |
| 19 | +
|
| 20 | +> [!NOTE] |
| 21 | +> These environment variables are required by Turborepo so it can call |
| 22 | +> the Turbo Cache Server with the right HTTP body, headers and query strings. |
| 23 | +> These environment variables are necessary so the Turborepo binary can |
| 24 | +> identify the Remote Cache feature is enabled and can use it across your |
| 25 | +> CI pipelines. You can [read more about this here](https://turbo.build/repo/docs/ci#setup) on the Turborepo official docs. |
| 26 | +
|
| 27 | +Make sure that you have an S3-compatible storage available. We currently tested with: |
| 28 | +
|
| 29 | +- [Amazon S3](https://aws.amazon.com/s3/) |
| 30 | +- [Cloudflare R2](https://www.cloudflare.com/en-gb/developer-platform/r2/) |
| 31 | +- [Minio Object Storage](https://min.io/) |
| 32 | +
|
| 33 | +2. Still on your `yml` file, after checking out your repository, use our custom |
| 34 | + action to start the Turbo Cache Server in the background: |
| 35 | + |
| 36 | +```yml |
| 37 | +- name: Checkout repository |
| 38 | + uses: actions/checkout@v4 |
| 39 | +
|
| 40 | +- name: Turborepo Cache Server |
| 41 | + uses: brunojppb/turbo-cache-server@0.0.2 |
| 42 | + env: |
| 43 | + PORT: '8585' |
| 44 | + S3_ACCESS_KEY: "YOUR_S3_ACCESS_KEY" |
| 45 | + S3_SECRET_KEY: "YOUR_S3_SECRET_KEY" |
| 46 | + S3_ENDPOINT": "YOUR_S3_ENDPOINT" |
| 47 | + S3_BUCKET_NAME: "YOUR_BUCKET_NAME" |
| 48 | + # Region defaults to "eu-central-1" |
| 49 | + S3_REGION: "eu-central-1" |
| 50 | + # if your S3-compatible store does not support requests |
| 51 | + # like https://bucket.hostname.domain/. Setting `S3_USE_PATH_STYLE` |
| 52 | + # to true configures the S3 client to make requests like |
| 53 | + # https://hostname.domain/bucket instead. |
| 54 | + # Defaults to "false" |
| 55 | + S3_USE_PATH_STYLE: false |
| 56 | +``` |
| 57 | +
|
| 58 | +And that is all you need to do use our remote cache server for Turborepo. |
| 59 | +
|
| 60 | +## How does that work? |
| 61 | +
|
| 62 | +Turbo Cache Server is a tiny web server written in [Rust](https://www.rust-lang.org/) that |
| 63 | +uses any S3-compatible bucket as its storage layer for the artifacts generated by Turborepo. |
| 64 | +
|
| 65 | +### What happens when there is a cache hit? |
| 66 | +
|
| 67 | +Here is a diagram showing how the Turbo Cache Server works within our actions during a cache hit: |
| 68 | +
|
| 69 | +```mermaid |
| 70 | +sequenceDiagram |
| 71 | + actor A as Developer |
| 72 | + participant B as Github |
| 73 | + participant C as Github Actions |
| 74 | + participant D as Turbo Cache Server |
| 75 | + participant E as S3 bucket |
| 76 | + A->>+B: Push new commit to GH.<br>Trigger PR Checks. |
| 77 | + B->>+C: Trigger CI pipeline |
| 78 | + C->>+D: turborepo cache server via<br/>"use: turbo-cache-server@0.0.2" action |
| 79 | + Note right of C: Starts a server instance<br/> in the background. |
| 80 | + D-->>-C: Turbo cache server ready |
| 81 | + C->>+D: Turborepo executes task<br/>(e.g. test, build) |
| 82 | + Note right of C: Cache check on the Turbo cache server<br/>for task hash "1wa2dr3" |
| 83 | + D->>+E: Get object with name "1wa2dr3" |
| 84 | + E-->>-D: object "1wa2dr3" exists |
| 85 | + D-->>-C: Cache hit for task "1wa2dr3" |
| 86 | + Note right of C: Replay logs and artifacts<br/>for task |
| 87 | + C->>+D: Post-action: Shutdown Turbo Cache Server |
| 88 | + D-->>-C: Turbo Cache server terminates safely |
| 89 | + C-->>-B: CI pipline complete |
| 90 | + B-->>-A: PR Checks done |
| 91 | +``` |
| 92 | +
|
| 93 | +### What happens when there is a cache miss? |
| 94 | +
|
| 95 | +When a cache isn't yet available, the Turbo Cache Server will handle new uploads and store the |
| 96 | +artifacts in S3 as you can see in the following diagram: |
| 97 | +
|
| 98 | +```mermaid |
| 99 | +sequenceDiagram |
| 100 | + actor A as Developer |
| 101 | + participant B as Github |
| 102 | + participant C as Github Actions |
| 103 | + participant D as Turbo Cache Server |
| 104 | + participant E as S3 bucket |
| 105 | + A->>+B: Push new commit to GH.<br>Trigger PR Checks. |
| 106 | + B->>+C: Trigger CI pipeline |
| 107 | + C->>+D: turborepo cache server via<br/>"use: turbo-cache-server@0.0.2" action |
| 108 | + Note right of C: Starts a server instance<br/> in the background. |
| 109 | + D-->>-C: Turborepo cache server ready |
| 110 | + C->>+D: Turborepo executes build task |
| 111 | + Note right of C: Cache check on the server<br/>for task hash "1wa2dr3" |
| 112 | + D->>+E: Get object with name "1wa2dr3" |
| 113 | + E-->>-D: object "1wa2dr3" DOES NOT exist |
| 114 | + D-->>-C: Cache miss for task "1wa2dr3" |
| 115 | + Note right of C: Turborepo executes task normaly |
| 116 | + C-->>C: Turborepo executes build task |
| 117 | + C->>+D: Turborepo uploads cache artifact<br/>with hash "1wa2dr3" |
| 118 | + D->>+E: Put object with name "1wa2dr3" |
| 119 | + E->>-D: Object stored |
| 120 | + D-->>-C: Cache upload complete |
| 121 | + C->>+D: Post-action: Turbo Cache Server shutdown |
| 122 | + D-->>-C: Turbo Cache server terminates safely |
| 123 | + C-->>-B: CI pipline complete |
| 124 | + B-->>-A: PR Checks done |
| 125 | +``` |
| 126 | +
|
| 127 | +## Development |
| 128 | +
|
| 129 | +Turbo Cache Server requires [Rust](https://www.rust-lang.org/) 1.75 or above. To setup your |
| 130 | +environment, use the rustup script as recommended by the |
| 131 | +[Rust docs](https://www.rust-lang.org/learn/get-started): |
| 132 | +
|
| 133 | +```shell |
| 134 | +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| 135 | +``` |
| 136 | + |
| 137 | +Now run the following command to run the web server locally: |
| 138 | + |
| 139 | +```shell |
| 140 | +cargo run |
| 141 | +``` |
| 142 | + |
| 143 | +### Setting up your environment |
| 144 | + |
| 145 | +During local development, you might want to try the Turbo Dev Server locally against a JS monorepo. As it depends on a S3-compatible service for storing Turborepo artifacts, we recommend using [Minio](https://min.io/) with Docker with the following command: |
| 146 | + |
| 147 | +```shell |
| 148 | +docker run \ |
| 149 | + -d \ |
| 150 | + -p 9000:9000 \ |
| 151 | + -p 9001:9001 \ |
| 152 | + --user $(id -u):$(id -g) \ |
| 153 | + --name minio1 \ |
| 154 | + -e "MINIO_ROOT_USER=minio" \ |
| 155 | + -e "MINIO_ROOT_PASSWORD=minio12345" \ |
| 156 | + -v ./s3_data:/data \ |
| 157 | + quay.io/minio/minio server /data --console-address ":9001" |
| 158 | +``` |
| 159 | + |
| 160 | +#### Setting up environment variables |
| 161 | +Copy the `.env.example` file, rename it to `.env` and add the environment |
| 162 | +variables required. As we use Minio locally, just go to the |
| 163 | +[Web UI](http://localhost:9001) of Minio, create a bucket and generate |
| 164 | +credentials and copy it to the `.env` file. |
| 165 | + |
| 166 | +### Tests |
| 167 | + |
| 168 | +To execute the test suite, run: |
| 169 | + |
| 170 | +```shell |
| 171 | +cargo test |
| 172 | +``` |
0 commit comments