@uknows/setup 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +209 -2
  3. package/bin/uknows-setup.mjs +14 -0
  4. package/lib/automate.mjs +1299 -0
  5. package/lib/check.mjs +327 -0
  6. package/lib/ci.mjs +21 -0
  7. package/lib/cli.mjs +251 -0
  8. package/lib/cloudid.mjs +456 -0
  9. package/lib/code.mjs +147 -0
  10. package/lib/context.mjs +126 -0
  11. package/lib/contract-docs.mjs +2736 -0
  12. package/lib/contract.mjs +149 -0
  13. package/lib/detect.mjs +627 -0
  14. package/lib/diff.mjs +147 -0
  15. package/lib/doc.mjs +98 -0
  16. package/lib/dockerfile.mjs +455 -0
  17. package/lib/endpoint.mjs +81 -0
  18. package/lib/engine.mjs +1753 -0
  19. package/lib/existing.mjs +562 -0
  20. package/lib/git.mjs +100 -0
  21. package/lib/hooks/UknowsOpenTelemetry.cs +118 -0
  22. package/lib/hooks/pins.mjs +28 -0
  23. package/lib/hooks/uknows-otel.cjs +82 -0
  24. package/lib/hooks/uknows_otel.py +179 -0
  25. package/lib/hosts.mjs +650 -0
  26. package/lib/locks.mjs +353 -0
  27. package/lib/manifest.mjs +132 -0
  28. package/lib/members.mjs +269 -0
  29. package/lib/plan.mjs +130 -0
  30. package/lib/settings.mjs +468 -0
  31. package/lib/signin.mjs +259 -0
  32. package/lib/stacks/azure.mjs +345 -0
  33. package/lib/stacks/channel.mjs +125 -0
  34. package/lib/stacks/dotnet.mjs +472 -0
  35. package/lib/stacks/functions-hooks.mjs +228 -0
  36. package/lib/stacks/functions.mjs +148 -0
  37. package/lib/stacks/guided.mjs +227 -0
  38. package/lib/stacks/index.mjs +18 -0
  39. package/lib/stacks/java.mjs +57 -0
  40. package/lib/stacks/k8s.mjs +31 -0
  41. package/lib/stacks/node.mjs +358 -0
  42. package/lib/stacks/otel.mjs +63 -0
  43. package/lib/stacks/python-bootstrap.mjs +71 -0
  44. package/lib/stacks/python-lock.mjs +105 -0
  45. package/lib/stacks/python-sets.mjs +143 -0
  46. package/lib/stacks/python.mjs +632 -0
  47. package/lib/toml.mjs +64 -0
  48. package/lib/types.mjs +208 -0
  49. package/lib/ui.mjs +225 -0
  50. package/lib/updates.mjs +398 -0
  51. package/lib/versions.mjs +115 -0
  52. package/lib/workspace.mjs +201 -0
  53. package/package.json +37 -4
package/LICENSE ADDED
@@ -0,0 +1,190 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ Copyright 2026 the UKNOWS authors
179
+
180
+ Licensed under the Apache License, Version 2.0 (the "License");
181
+ you may not use this file except in compliance with the License.
182
+ You may obtain a copy of the License at
183
+
184
+ http://www.apache.org/licenses/LICENSE-2.0
185
+
186
+ Unless required by applicable law or agreed to in writing, software
187
+ distributed under the License is distributed on an "AS IS" BASIS,
188
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
189
+ See the License for the specific language governing permissions and
190
+ limitations under the License.
package/README.md CHANGED
@@ -1,3 +1,210 @@
1
- # Temporary Holding Version
1
+ # @uknows/setup
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Add standard OpenTelemetry to your app, so it sends traces and logs to UKNOWS.
4
+
5
+ Run it in the root folder of your repo:
6
+
7
+ ```sh
8
+ npx @uknows/setup
9
+ ```
10
+
11
+ 1. It finds each service in your repo: its language, its framework, its Dockerfile or start command, and where it runs.
12
+ 2. It opens your browser. You sign in to UKNOWS and pick the workspace and the environment. Check that the browser shows the same code as the terminal. Your key then comes to the tool by itself: you never create, copy or paste it. The tool checks the key: UKNOWS says which workspace and environment the key sends to, and the tool sends 1 test span. A new key can take up to 2 minutes to reach the data intake of UKNOWS. The tool waits for it.
13
+ 3. It shows the whole plan: each file it changes and how many lines, how the agent stays up to date and why, where it stores your key (the app, the resource group and the subscription, a GitHub secret or a Kubernetes secret), the deploy file that would remove the key on the next deploy, the branch and the pull request, and the link where you watch your app connect. To show this, it reads your Azure subscriptions, your GitHub repo or your kubectl contexts. Nothing changes yet.
14
+ 4. It asks 1 question: `Do all of this? (Y/n)`. Type d to see every line that changes first. Press Enter to go ahead, or type n to stop.
15
+ 5. It does every step and shows 1 line for each, done or failed: it changes the files with your own package manager, stores the key (az, gh and kubectl read it from a pipe, never from a file or a command line), adds the key to the deploy file, and creates a branch with 1 commit of exactly the files it changed, pushes it and opens a pull request. On GitHub, the commit goes up through the GitHub API, so GitHub signs it and a branch rule that requires signed commits passes.
16
+ 6. The last line says what is left: merge the pull request and deploy as usual. It ends with the link to the page where you watch your app connect, and the tool opens it in your browser.
17
+
18
+ While the tool waits for your sign-in, press Enter to open the browser again, p to paste a key instead, or Ctrl+C to stop. Over ssh, or on a computer with no browser, open the link that it prints on any device. If the sign-in is cancelled in the browser or the link expires, it asks if you want to try again or paste a key. With `--paste-key`, it asks for the key instead of opening the browser. The key does not show on the screen, and the tool never writes it to a file in your repo.
19
+
20
+ If a step cannot be done, for example `az` is not signed in, the plan says why, and the tool prints that step for you at the end. If the tool did not store your key, the last line says so: store the key before you merge, with `npx @uknows/setup key` or the key steps that the tool printed. If your branch has commits that are not on origin yet, the tool creates the branch and the commit but does not push, so your own commits never go out with the 1 yes. It prints the push command. `npx @uknows/setup remove` undoes the change.
21
+
22
+ With `--step-by-step`, the tool changes the files first, then asks before each of the other steps, one at a time.
23
+
24
+ The sign-in and the questions come only in a terminal. With `--yes` or `--json`, in a pipeline or without a terminal, the tool signs in to nothing, asks nothing, stores no key and opens no pull request. It prints the steps for you instead.
25
+
26
+ Run it once on your computer, not in your pipeline. Your pipeline only builds and deploys the change, and sets your key on your app. See "CI/CD and pipelines" below.
27
+
28
+ Full docs: https://uknows.my/docs
29
+
30
+ ## What it supports
31
+
32
+ | Stack | What setup does |
33
+ |---|---|
34
+ | Node.js (CommonJS and ES modules) | Adds the OpenTelemetry packages with npm, pnpm or yarn, adds the start file `uknows-otel.cjs` and loads it with `NODE_OPTIONS` or the start script, adds the 5 settings. |
35
+ | Python | Adds the packages to `requirements.txt` or `pyproject.toml`, refreshes `uv.lock` or `poetry.lock` with your own uv or Poetry, starts the app with `opentelemetry-instrument`, adds the 5 settings. In a Dockerfile, it also adds the UKNOWS log bridge, so the logs go to UKNOWS and the app prints exactly what it printed before. |
36
+ | Java (also Keycloak images) | Copies the OpenTelemetry Java agent from its image, pinned by digest, into the Dockerfile, loads it with `JAVA_TOOL_OPTIONS`, adds the 5 settings. |
37
+ | .NET | Adds `OpenTelemetry.AutoInstrumentation` to the project file, refreshes `packages.lock.json` with `dotnet restore`, starts the app with `instrument.sh`, adds the 5 settings. |
38
+ | Go, PHP, Ruby | Adds the 5 settings, then prints the code steps for you to do. For Go 1.23, 1.24 and 1.25, the `go get` lines name the OpenTelemetry versions for that Go. |
39
+ | Azure Functions (Node.js v4 model, Python v2 model, .NET isolated) | If the function app does not send to Application Insights, adds 1 line to `host.json`. If it does, or setup cannot tell, adds small UKNOWS hooks to the code of the app instead, so Application Insights stays exactly as it is. The settings and the key go on the function app as app settings. |
40
+ | Already uses OpenTelemetry | Adds only the settings. Keeps a Collector address and shows what to change. |
41
+
42
+ | Where it runs | Found from |
43
+ |---|---|
44
+ | Docker and VMs (Amazon EC2, Azure VMs, Alibaba ECS and others) | Dockerfile, Compose, systemd, cloud-init, Alibaba ECS in Terraform |
45
+ | Kubernetes (AKS, EKS, GKE, Alibaba ACK) | Kubernetes manifests, Helm charts, kubectl and helm deploy steps, Alibaba ACK in Terraform |
46
+ | Azure Container Apps | Terraform, Bicep, `az containerapp`, the deploy action, `azure.yaml` |
47
+ | Azure App Service | Terraform, Bicep, `az webapp`, the deploy action, `azure.yaml` |
48
+ | Azure Functions | Terraform, Bicep, `az functionapp`, the deploy action, `azure.yaml`, `host.json` |
49
+ | AWS ECS and Fargate | Terraform, CloudFormation, task definition files, `aws ecs`, the deploy action, Copilot |
50
+ | Alibaba SAE | Terraform, `aliyun sae`, SAE addresses |
51
+
52
+ For each place it finds, it prints the steps to set your key once as a secret there, or in a terminal asks to do them for you. Then it checks your deploy files, so the next deploy keeps the key: `--replace-env-vars`, the `environmentVariables` or `yamlConfigPath` of the Container Apps deploy action, Bicep and Terraform templates, App Service slots, ECS task definition files, Kubernetes and GitHub Actions. Each check names the file and line.
53
+
54
+ For a container app, setup also adds `OTEL_RESOURCE_ATTRIBUTES` with the Azure resource id of the app to the command that deploys it, so UKNOWS links the data to that exact app. It does this only when the deploy command names the subscription, the resource group and the app, and it never changes a value that you set. For an Azure VM, the key steps end with Mark each deploy: a step for the end of each deploy that sends 1 log record with the service name and the resource id of the VM, so UKNOWS knows when a deploy happened.
55
+
56
+ ## What it changes
57
+
58
+ - **Packages.** It adds the upstream OpenTelemetry packages for your stack:
59
+ - Node.js: `@opentelemetry/api` and `@opentelemetry/auto-instrumentations-node`, with npm, pnpm or yarn.
60
+ - Python: `opentelemetry-distro`, the OTLP exporter and the packages for your libraries, in your requirements file or `pyproject.toml`. A requirements file gets exact versions that fit your app: for example, `protobuf<5` gets OpenTelemetry 1.27.0, and the plan says why. A uv or Poetry project gets lower limits, and the tool runs `uv lock` (in the workspace root) or `poetry lock` on your computer, so your own resolver picks the versions. Your uv must be the version that your project or your image asks for.
61
+ - .NET: `OpenTelemetry.AutoInstrumentation` in your project file, plus `OpenTelemetry.Instrumentation.StackExchangeRedis` when your app uses StackExchange.Redis, also through a package such as NRedisStack. With `packages.lock.json`, the tool runs `dotnet restore --force-evaluate` with the `-r` of your Dockerfile. It needs a .NET SDK for your target framework on your computer.
62
+ - Java: the OpenTelemetry Java agent, copied into your image from the OpenTelemetry image, pinned by its digest. It needs no BuildKit.
63
+ - Azure Functions with the UKNOWS hooks: the OpenTelemetry packages of the hooks, at the versions that UKNOWS tested. If your app uses another version of the Functions library, the plan says so and asks you to check UKNOWS after the deploy.
64
+ - **Lockfiles.** The tool records the lockfile that uv, Poetry or dotnet rewrites, so `remove` gives it back byte for byte without running the tool again. If the resolver finds no versions that fit, or the lockfile format changes, the tool puts every file back and says why.
65
+ - **Startup.** It loads OpenTelemetry when your app starts, in your Dockerfile or start script. New Dockerfile lines go after your last `RUN`, so build steps never load OpenTelemetry. Lines you already have, such as `NODE_OPTIONS`, stay as they are.
66
+ - Node.js: it adds `uknows-otel.cjs` next to `package.json`. The file starts OpenTelemetry. On SIGTERM it sends the last data, then stops the app, also as PID 1 in a container. An app with its own SIGTERM handler keeps it. In a Dockerfile, a `COPY` line puts the file in the `WORKDIR` of the final stage. If the tool cannot tell the build context or the `WORKDIR`, or `.dockerignore` leaves the file out, it loads the OpenTelemetry register line instead and tells you why. For Python, it changes the start command only when your image installs the file that it changed. With `uv run` or `poetry run`, `opentelemetry-instrument` goes after `run` and its options. A `Procfile` never changes: the tool prints its new line as a step.
67
+ - Azure Functions: 1 line in `host.json`, `"telemetryMode": "OpenTelemetry"`, when the function app does not send to Application Insights. Otherwise the UKNOWS hooks: `uknows-otel.cjs` for Node.js, loaded through `"main"` in `package.json`; `uknows_otel.py` and 2 lines in `function_app.py` for Python; `UknowsOpenTelemetry.cs` and 2 lines in `Program.cs` for .NET. A Python function app also needs the app setting `PYTHON_ENABLE_WORKER_EXTENSIONS=1`, which setup lists with the other app settings. If the hooks are needed but cannot apply, for example to the Node.js v3 model or the .NET in-process model, setup changes nothing for that app and says why. `--functions-opentelemetry` puts the line in `host.json` instead of the hooks.
68
+ - **Logs.** The setting `OTEL_LOGS_EXPORTER=otlp` sends the logs of your app to UKNOWS. A log line written during a request carries the trace id of that request.
69
+ - Python: the OpenTelemetry logging handler stays off the root logger (`OTEL_PYTHON_LOG_AUTO_INSTRUMENTATION=false`), and the UKNOWS log bridge sends the log records instead. The bridge is a small folder, `uknows-otel`, that your image copies. Your app prints exactly what it printed before. A Python app that does not start with `opentelemetry-instrument` in its image sends traces only.
70
+ - .NET: `OTEL_DOTNET_AUTO_LOGS_INCLUDE_FORMATTED_MESSAGE=true`, so a log line keeps its values.
71
+ - **Settings.** It adds 5 settings where your app keeps settings: your Dockerfile, your Kubernetes manifest, or `otel.env` when your repo has it or a file in your repo loads it (a systemd `EnvironmentFile=`, a Compose `env_file:`, `--env-file` or `. ./otel.env`). Otherwise it adds no file and prints the settings in the form of your platform, as a step for you.
72
+ - `OTEL_SERVICE_NAME`
73
+ - `OTEL_EXPORTER_OTLP_ENDPOINT`
74
+ - `OTEL_EXPORTER_OTLP_PROTOCOL`
75
+ - `OTEL_METRICS_EXPORTER`
76
+ - `OTEL_LOGS_EXPORTER`
77
+
78
+ Some stacks get 1 or 2 more, and the plan lists them: for example, the resource detectors that send the host name of a Node.js or Python app, and the log settings of .NET above.
79
+ - **Updates.** Setup keeps the UKNOWS agent up to date by itself. The plan and the pull request say which way it picked and why:
80
+ 1. **The agent channel**, for Java, .NET and Node.js apps that build from a Dockerfile: 1 `COPY` line that takes the UKNOWS agent from the agent image of the stable channel at each build, and the settings that start it. Packages, lockfiles and the start command stay as they are, and a new agent reaches the app at its next build, so no update pull request is needed. If the agent files are missing or damaged, the app starts without the agent. The agent images are in `registry.uknows.my/uknows`, and your build pulls them without signing in, so a firewall in front of your builds must let them reach `registry.uknows.my` on port 443.
81
+ 2. **Renovate**, for the other apps, when your repo uses Renovate already: a Renovate config file, or a `"renovate"` key in `package.json`. Setup never changes your config. It prints the rule to add for the UKNOWS and OpenTelemetry packages.
82
+ 3. **Dependabot**, on GitHub, when your repo does not use Renovate: `.github/dependabot.yml` and the workflow `.github/workflows/uknows-updates.yml`. Dependabot proposes the OpenTelemetry updates, and the workflow merges them when the checks that your branch rules require pass, then starts your deploy.
83
+ 4. On GitLab, Azure DevOps or Bitbucket, when your repo does not use Renovate: `renovate.json`, and 1 step for you: install the free Mend Renovate app for the repository. Renovate then proposes the UKNOWS and OpenTelemetry updates in 1 pull request, 3 days after each release, and merges it when your checks pass.
84
+
85
+ Azure Functions apps get no update bot: the UKNOWS hooks stay on the versions that UKNOWS tested. A repo with no `origin` remote gets none either, and the plan says how to add one. `--update-bot renovate`, `--update-bot dependabot`, `--update-bot none` and `--channel` choose instead of setup, and a rerun keeps the choice. Choosing never stops setup.
86
+ - **A record.** It writes `.uknows/setup.json`, so `remove` can undo exactly what it changed. This file has no secrets. Commit it.
87
+
88
+ For Go, PHP and Ruby, it adds the settings and prints the steps to do by hand.
89
+
90
+ If your app already uses OpenTelemetry, it adds only the settings. If your app sends data to another address, such as an OpenTelemetry Collector, it keeps that address and its settings and shows you what to change. If your app uses Azure Monitor, it keeps it and adds UKNOWS beside it. If your app already uses another APM agent, it stops and explains your options.
91
+
92
+ A frontend, such as a React app that nginx serves, gets no change. UKNOWS traces server apps.
93
+
94
+ ## Your key
95
+
96
+ Your key goes in `OTEL_EXPORTER_OTLP_HEADERS`. Set it once for each environment as a secret on your platform. In a terminal, setup stores the key of the environment that you picked when you signed in, or prints the steps for the platform it found in your repo. If `OTEL_EXPORTER_OTLP_HEADERS` is set in your terminal, setup uses that key instead of signing you in, and the plan names its workspace and environment.
97
+
98
+ For another environment, for example Production, run `npx @uknows/setup key` in the repo. It signs you in again, so you pick that environment, then checks the key and asks to store it in the same way. With `--paste-key`, it asks you to paste that key instead. It changes no file.
99
+
100
+ Never put the key in a file in your repo.
101
+
102
+ The tool checks your key as soon as it gets it. To check it again later, run these 3 lines in bash. Paste your key when it asks. The key does not show on the screen and does not go in your shell history.
103
+
104
+ ```sh
105
+ read -rsp 'Paste your UKNOWS key: ' UKNOWS_KEY; echo
106
+ export OTEL_EXPORTER_OTLP_HEADERS="x-uknows-key=$UKNOWS_KEY"
107
+ npx @uknows/setup check
108
+ ```
109
+
110
+ `check` asks UKNOWS which workspace and environment the key sends to, then sends 1 test span. A key that UKNOWS refuses gets its reason: not known, revoked, or a paused workspace. Apart from your package manager, the tool uses the network for the sign-in, the check and the steps after it. In a terminal, it reads your Azure subscriptions, your GitHub repo or your kubectl contexts to show the plan. It changes nothing there until you say yes. Setup runs your package manager with install scripts turned off, so no install script of your project or its packages runs. uv lock and dotnet restore can run your own project's build code to read its metadata. With a lockfile, npm and pnpm change only `package.json` and the lockfile.
111
+
112
+ ## Commands and options
113
+
114
+ ```text
115
+ npx @uknows/setup [setup] [options] Find your app, show the plan, then apply it.
116
+ npx @uknows/setup key [--path <dir>] Sign in, check and store the key of another environment.
117
+ npx @uknows/setup remove [options] Undo what setup changed.
118
+ npx @uknows/setup check [--json] Check your key and send 1 test span.
119
+ ```
120
+
121
+ | Option | What it does |
122
+ |---|---|
123
+ | `--dry-run` | Show the plan. Change nothing. |
124
+ | `--yes`, `-y` | Apply without asking. It never asks any question and never signs in. In a terminal with `OTEL_EXPORTER_OTLP_HEADERS` set, it checks that key. |
125
+ | `--step-by-step` | Ask before each step, instead of 1 question for the whole plan. The files change first. |
126
+ | `--paste-key` | Paste your key instead of signing in to UKNOWS in your browser. Also works with `key`. |
127
+ | `--allow-ci` | Apply in a pipeline. Use it only for a bot or an AI agent that opens a pull request. |
128
+ | `--path <folder>` | The folder to set up. The default is the current folder. |
129
+ | `--all` | Set up every service folder in a monorepo. Each one gets its own `OTEL_SERVICE_NAME`. |
130
+ | `--service-name <name>` | The name of the service in UKNOWS. Use lowercase letters, digits and `-`. |
131
+ | `--channel <name>` | Java, .NET and Node.js apps with a Dockerfile: copy the UKNOWS agent from the agent image of a channel, `stable` or `early`, at each build. |
132
+ | `--update-bot <name>` | `renovate`, `dependabot` or `none`: how the OpenTelemetry packages of your app stay up to date. Dependabot works on GitHub only. Without it, setup picks, as "Updates" says. |
133
+ | `--functions-opentelemetry` | Azure Functions apps: turn on OpenTelemetry in `host.json` instead of adding the UKNOWS hooks. Application Insights then names each request by its route instead of the name of the function. |
134
+ | `--json` | Print a JSON report. Without `--yes`, setup only plans. |
135
+ | `--force` | Run even when the repo has changes that are not committed. With `remove`, delete the record even when some changes could not be undone. |
136
+ | `--check` | The same as the `check` command. |
137
+
138
+ Setup stops when your repo has changes that are not committed, so you can review exactly what it changed with `git diff`. Commit or stash your changes first, or use `--force`.
139
+
140
+ With `--path`, setup still reads the deploy files at the top of the git repo, such as `k8s/` and `.github/workflows/`, to find where your app runs. If the folder is part of a JavaScript workspace, or its .NET package versions are set in a file above it, setup changes nothing and asks you to run it from the repo root. There, pick the service from the list, or use `--all`.
141
+
142
+ ## CI/CD and pipelines
143
+
144
+ Run setup once, on your computer, in your repo. Do not run it in your pipeline.
145
+
146
+ 1. Run `npx @uknows/setup` in your repo. Review the diff. Commit the change and open a pull request.
147
+ 2. Your pipeline builds and deploys the change as usual. It needs no UKNOWS step to build.
148
+ 3. Store your key in the secret store of your pipeline, once for each environment.
149
+ 4. In your deploy job, check that the secret is not empty. Set the key on your app before the deploy that uses it.
150
+ 5. If your deploy replaces all environment variables, add the key to that list. Otherwise each deploy removes the key.
151
+
152
+ Setup and remove stop with exit code 2 when they run in a pipeline. A run counts as a pipeline when `CI` (not `0` or `false`), `GITHUB_ACTIONS`, `TF_BUILD`, `GITLAB_CI`, `BUILDKITE`, `CIRCLECI`, `JENKINS_URL`, `TEAMCITY_VERSION`, `BITBUCKET_BUILD_NUMBER` or `CODEBUILD_BUILD_ID` is set. `--dry-run`, `--json` without `--yes`, `check`, `--help` and `--version` still work there.
153
+
154
+ To check in a pipeline that a repo is set up, run this step. It changes nothing, and it fails unless the repo is set up:
155
+
156
+ ```bash
157
+ npx @uknows/setup --dry-run --json | jq -e '.status == "nothing-to-change" and .exitCode == 0'
158
+ ```
159
+
160
+ A repo is set up when `"status"` is `"nothing-to-change"` and `"exitCode"` is `0`. That needs a commit with `.uknows/setup.json`, which lists every service, or a repo with no step left. Steps that the repo cannot show, such as the settings on your platform, are then listed in `manual[]` but do not change the exit code. In a monorepo, the check plans the services that `.uknows/setup.json` lists, so it needs no `--all`. Other statuses mean that the repo is not set up yet: `"planned"` (setup has changes to make), `"needs-steps"` (exit code 3: setup can change nothing, and the listed steps are yours, such as installing uv), and `"needs-selection"` (exit code 2: pick the services with `--all` or `--path`).
161
+
162
+ ## Exit codes
163
+
164
+ The exit code describes your repo. Setting your key on your platform, merging the pull request and deploying never change it. In a terminal, a key that UKNOWS refuses ends setup with exit code 1 before anything changes. With `--step-by-step`, the key comes after the files, so the changes to your repo stay. Ctrl+C while setup waits for your sign-in stops it with exit code 130, and nothing changes.
165
+
166
+ | Code | setup | remove | check |
167
+ |---|---|---|---|
168
+ | 0 | Applied, already set up, or a dry run with no required step. Only the key steps on your platform are left. A frontend-only repo also gets 0. A repo that setup set up gets 0 on the next run, also when steps that the repo cannot show are listed. | Removed, or nothing to remove. | The key works and UKNOWS accepted the test span. |
169
+ | 1 | Stopped or failed, and nothing changed. For example, a dirty repo, a key in a file, another APM agent, a package manager error, or no app found. In a terminal, also a key that UKNOWS refuses. | Failed. | Refused, or a network error. |
170
+ | 2 | Needs your input, and nothing changed. For example, a usage error, a service to pick, no terminal and no `--yes`, or a pipeline without `--allow-ci`. | The same. | No key. |
171
+ | 3 | Applied or planned, but you must do 1 or more steps in your repo before traces flow. The tool prints them. With nothing to change and no `.uknows/setup.json` yet, the status is `"needs-steps"`. | Partial. Some changes are left. | |
172
+
173
+ `key` exits 0 when it stored the key or printed its steps, 1 when the folder is not set up or UKNOWS refuses the key or cannot be reached, and 2 without a terminal or without a key.
174
+
175
+ In `--json`, `ci` says if the run counts as a pipeline, `services[].mode` says how the tool sets up each service, and `manual[].required` says if a step counts toward exit code 3. Advice never does.
176
+
177
+ ## Undo
178
+
179
+ ```sh
180
+ npx @uknows/setup remove
181
+ ```
182
+
183
+ `remove` runs your package manager to remove the packages that setup added. Then it puts back every line that setup changed and deletes the files that setup created. If you changed those lines after setup, it skips that file, tells you, and keeps the record so you can run `remove` again. If your package manager does not write `package.json` or the lockfile back byte for byte, `remove` names the file, so you can check it with `git diff`.
184
+
185
+ ## Requirements
186
+
187
+ Node.js 18 or later, on macOS, Linux or Windows. The tool has no dependencies.
188
+
189
+ ## Test addresses
190
+
191
+ Setup writes `OTEL_EXPORTER_OTLP_ENDPOINT` with the UKNOWS ingest address, and check asks the UKNOWS site about your key. The last line links to the UKNOWS app, where you watch your app connect. To use a test copy of UKNOWS, set its addresses. The test copy's `/docs` page gives the command with them:
192
+
193
+ ```sh
194
+ UKNOWS_SITE_URL=https://uknows-test.example.com UKNOWS_APP_URL=https://app-test.example.com UKNOWS_INGEST_ENDPOINT=https://ingest-test.example.com/otlp npx @uknows/setup
195
+ ```
196
+
197
+ They must be https addresses. On your own computer, `http://127.0.0.1` and `http://localhost` work too. With only `UKNOWS_INGEST_ENDPOINT`, check sends the test span but does not ask which workspace the key sends to. Setup signs you in at the app address. Without `UKNOWS_APP_URL`, a run with a test address cannot sign you in: it tells you to set `UKNOWS_APP_URL`, asks you to paste the key, prints no link to the app and opens no browser. If the test copy cannot make a sign-in link, setup says so and asks you to paste the key.
198
+
199
+ `UKNOWS_AGENT_REGISTRY` sets another store of the UKNOWS agent images for the agent channel, as a registry and path, for example `registry.example.com/uknows`.
200
+
201
+ To build a package for a test environment, bake its addresses in, the same build settings that `/docs` uses. Do not commit the result:
202
+
203
+ ```sh
204
+ VITE_UKNOWS_SITE_URL=https://uknows-test.example.com \
205
+ VITE_UKNOWS_APP_URL=https://app-test.example.com \
206
+ VITE_UKNOWS_INGEST_HOST=ingest-test.example.com \
207
+ node tools/sync-contract.mjs
208
+ npm pack
209
+ git checkout lib/contract-docs.mjs
210
+ ```
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ // npx @uknows/setup: add OpenTelemetry to an app so it sends traces to UKNOWS.
3
+ const major = Number(process.versions.node.split('.')[0])
4
+ if (major < 18) {
5
+ console.error(`uknows-setup needs Node.js 18 or later. This is Node.js ${process.versions.node}.`)
6
+ process.exit(1)
7
+ }
8
+ try {
9
+ const { main } = await import('../lib/cli.mjs')
10
+ process.exitCode = await main(process.argv.slice(2))
11
+ } catch (error) {
12
+ console.error(`Something went wrong: ${error?.message ?? error}`)
13
+ process.exitCode = 1
14
+ }