|
| 1 | +# Benchling App Example: Chemical Sync for Local Development |
| 2 | + |
| 3 | +An example Benchling App written in Python which allows users to search for chemicals |
| 4 | +via [PubChem](https://pubchem.ncbi.nlm.nih.gov/) and create them in Benchling. |
| 5 | + |
| 6 | + |
| 7 | +_The App features branching flows and will also validate user inputs._ |
| 8 | + |
| 9 | +## Technical Prerequisites |
| 10 | + |
| 11 | +This app is optimized as a minimal local development experience using [Docker](https://www.docker.com/) for reproducibility. |
| 12 | + |
| 13 | +> ⚠️ **Development Only**: This example is not meant to be copied into production as-is. There are additional deployment, scale, and security concerns that should be addressed before deploying an app based on this example to production. |
| 14 | +
|
| 15 | +It relies on a few other tools that will be installed for you within Docker containers: |
| 16 | +* [Localtunnel](https://localtunnel.me/) - expose a public webhook URL and forward the results locally. ⚠️ *Not for production or real data!* |
| 17 | +* [Flask](https://flask.palletsprojects.com/) - A simple Python web application framework |
| 18 | + |
| 19 | +## Getting Started |
| 20 | + |
| 21 | +Create an empty placeholder file for Docker secrets. *nix example: |
| 22 | + |
| 23 | +```bash |
| 24 | +touch .client_secret |
| 25 | +``` |
| 26 | + |
| 27 | +Start Docker: |
| 28 | + |
| 29 | +```bash |
| 30 | +docker compose up --build -d |
| 31 | +``` |
| 32 | + |
| 33 | +Tip: You can omit the `-d` option if you want to run in the foreground. Otherwise, use `docker compose logs -f` to tail logs. |
| 34 | + |
| 35 | +You can verify that Flask is up and running: |
| 36 | + |
| 37 | +```bash |
| 38 | +curl localhost:8000/health |
| 39 | +``` |
| 40 | + |
| 41 | +If Flask is running, you should see `OK` printed. |
| 42 | + |
| 43 | +Be sure to note the URL created for you by `localtunnel`. The log line should look something like this: |
| 44 | + |
| 45 | +``` |
| 46 | +app-workshop-local-tunnel-1 | your url is: https://brave-wombats-poke.loca.lt |
| 47 | +``` |
| 48 | + |
| 49 | +On *nix systems, you can easily obtain _just_ the URL via: |
| 50 | + |
| 51 | +``` |
| 52 | +docker compose logs local-tunnel | grep -o https://.* | tail -n 1 |
| 53 | +``` |
| 54 | + |
| 55 | +Example Output: |
| 56 | + |
| 57 | +``` |
| 58 | +https://brave-wombats-poke.loca.lt |
| 59 | +``` |
| 60 | + |
| 61 | +> 💡 Don't forget to append `/1/webhooks`, making the full URL given to Benchling `https://brave-wombats-poke.loca.lt/1/webhooks` |
| 62 | +
|
| 63 | +## Setting Up Your App in Benchling |
| 64 | + |
| 65 | +### Benchling Prerequisites |
| 66 | +1. Access to a Benchling tenant, like `https://my-tenant.benchling.com` |
| 67 | +2. Ensure you've been granted access to the [Benchling Developer Platform Capability](https://help.benchling.com/hc/en-us/articles/9714802977805-Access-the-Benchling-Developer-Platform). |
| 68 | +3. This example also requires a [Lab Automation](https://www.benchling.com/resources/benchling-lab-automation) license. |
| 69 | +4. [Molecule entities](https://help.benchling.com/hc/en-us/articles/9684254682893-Molecule-entity-overview) will need to be enabled on your tenant. |
| 70 | + |
| 71 | +### Upload the App Manifest |
| 72 | + |
| 73 | +Click the user icon in the bottom left corner to bring up the main menu. Select "Feature Settings" > "Developer Console" |
| 74 | + |
| 75 | +Next, click the "Create app" button and choose "From manifest." |
| 76 | + |
| 77 | +When prompted to upload a file, select `manifest.yaml` and click "Create." |
| 78 | + |
| 79 | + |
| 80 | + |
| 81 | +### Update the Webhook URL |
| 82 | + |
| 83 | +Every time we restart the `local-tunnel` Docker container, it will provision |
| 84 | +a new public webhook URL. |
| 85 | + |
| 86 | +Update the Benchling App's Webhook URL in the UI with the new server and |
| 87 | +append the path our Flask route expects (see `local_app/app.py`). |
| 88 | + |
| 89 | +For example, if our `localtunnel` generated URL is `https://hot-ideas-doubt.loca.lt`, |
| 90 | +the webhook URL in Benchling should be: |
| 91 | + |
| 92 | +``` |
| 93 | +https://hot-ideas-doubt.loca.lt/1/webhooks |
| 94 | +``` |
| 95 | + |
| 96 | + |
| 97 | + |
| 98 | +### Generating a Client Secret |
| 99 | + |
| 100 | +Generate a client secret in Benchling and be sure to copy the secret. |
| 101 | + |
| 102 | + |
| 103 | + |
| 104 | +One easy way to set these environment variables for Docker is to add a `.env` file. |
| 105 | + |
| 106 | +```bash |
| 107 | +touch .env |
| 108 | +``` |
| 109 | + |
| 110 | +Open it in an editor of your choice and set the values with the plaintext client ID |
| 111 | +for your App. For example: |
| 112 | + |
| 113 | +``` |
| 114 | +CLIENT_ID=42a0cd39-0543-4dd2-af02-a866c97f0c4d |
| 115 | +``` |
| 116 | + |
| 117 | +Since the client secret is sensitive, it's handled a bit differently. It's |
| 118 | +registered as a `secret` in our `docker-compose.yaml` file, which will be looking |
| 119 | +for a file `./client_secret`. |
| 120 | + |
| 121 | +We can create this file and paste in the secret plaintext value if we have the secret in our clipboard. |
| 122 | +On *nix: |
| 123 | + |
| 124 | +```bash |
| 125 | +touch .client_secret |
| 126 | +pbpaste > .client_secret |
| 127 | +``` |
| 128 | + |
| 129 | +> ⚠️ **Security Note:** Be sure to avoid committing `.client_secret` to a source code repository. |
| 130 | +
|
| 131 | +You'll then need to restart _just_ the `benchling-app` Docker service to pick up the changes: |
| 132 | + |
| 133 | +``` |
| 134 | +docker-compose up -d |
| 135 | +``` |
| 136 | + |
| 137 | +If you restart both containers, be sure to update your App in Benchling with the new webhook URL from localtunnel. |
| 138 | + |
| 139 | +> ⚠️ **Security Note:** In production, store the secret with a secure solution such as a secrets store (AWS Secrets Manager, as an example) or, if storing programmatically, encrypted using app-layer encryption. Avoid placing it in plaintext anywhere in code or configuration. |
| 140 | +
|
| 141 | +### Create App Registry Dependencies |
| 142 | + |
| 143 | +If you examine the `configuration` section of `manifest.yaml`, you'll see our App |
| 144 | +expects a few configuration items: |
| 145 | +1. A folder |
| 146 | +2. A molecule entity schema with two decimal fields |
| 147 | + |
| 148 | +The `features` section of `manifest.yaml` also states that our App will render |
| 149 | +its UI on an `ASSAY_RUN`. So we'll also need: |
| 150 | +1. An Lab Automation run schema |
| 151 | + |
| 152 | +#### Folder |
| 153 | + |
| 154 | +Create a new folder where the molecules created by the App will be placed. |
| 155 | +An existing folder can also be used, if the App has permissions to it. |
| 156 | + |
| 157 | + |
| 158 | + |
| 159 | +#### Molecule Entity Schema |
| 160 | + |
| 161 | +Create the entity schema in the tenant's registry. If you do not have access to |
| 162 | +the registry, you can ask your tenant administrator to do this for you. |
| 163 | + |
| 164 | + |
| 165 | + |
| 166 | +The created molecule schema should look something like this: |
| 167 | + |
| 168 | + |
| 169 | + |
| 170 | +_Note: The names can be different, and the schema is allowed to have additional fields. |
| 171 | +As long as it's for a `Molecule` entity, and has at least two `Decimal` fields._ |
| 172 | + |
| 173 | +#### Lab Automation Run Schema |
| 174 | + |
| 175 | +Create a new lab automation run schema in the registry. |
| 176 | + |
| 177 | + |
| 178 | + |
| 179 | +### Updating the App's Configuration |
| 180 | + |
| 181 | +App Configuration gives us a stable code contract for referencing data mapped in a Benchling tenant. |
| 182 | +The values of the data in Benchling can then be changed without updating App code. |
| 183 | + |
| 184 | +Let's update our configuration to: |
| 185 | +1. Specify a folder for syncing sequences |
| 186 | +2. Link a molecule schema and fields for the synced chemicals |
| 187 | +3. Select an assay run schema to associate with our Benchling App |
| 188 | + |
| 189 | + |
| 190 | + |
| 191 | +### Permission the App |
| 192 | + |
| 193 | +By default, Benchling Apps do not have permission to any data in Benchling. |
| 194 | +Let's grant some access by adding the Benchling App to an organization. |
| 195 | + |
| 196 | + |
| 197 | + |
| 198 | +## Running the App - Syncing a Chemical |
| 199 | + |
| 200 | +1. Create a new notebook entry |
| 201 | +2. Insert a run of the schema linked in App Config |
| 202 | +3. Create the Run |
| 203 | +4. Enter a valid chemical name to search for, such as `acetaminophen` |
| 204 | +5. Click "Search Chemicals" |
| 205 | +6. After reviewing the preview, click "Create Molecule" |
| 206 | +7. Click the linked entity to view it in Benchling |
| 207 | + |
| 208 | + |
0 commit comments