Skip to content

Commit c17269b

Browse files
Merge branch 'main' into tj/ai-seat-cell-icons
2 parents 3647a21 + 787392e commit c17269b

39 files changed

Lines changed: 1722 additions & 126 deletions

.github/workflows/weekly-docs.yaml

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,18 +117,83 @@ jobs:
117117
# See: https://github.com/UmbrellaDocs/action-linkspector/issues/62
118118
PUPPETEER_EXECUTABLE_PATH: ${{ needs.prepare-linkspector-browser.outputs.chrome-path }}
119119
with:
120-
reporter: github-pr-review
120+
# On PRs, use github-pr-review for inline comments. On schedule/dispatch,
121+
# use local so reviewdog actually reports failures instead of silently
122+
# exiting 0 (github-pr-review requires a PR context).
123+
reporter: ${{ github.event_name == 'pull_request' && 'github-pr-review' || 'local' }}
121124
config_file: ".github/.linkspector.yml"
122125
fail_on_error: "true"
123-
filter_mode: "file"
126+
filter_mode: ${{ github.event_name == 'pull_request' && 'file' || 'nofilter' }}
124127

125128
- name: Send Slack notification
126-
if: failure() && github.event_name == 'schedule'
129+
if: failure() && github.event_name != 'pull_request'
127130
run: |
128131
curl \
129132
-X POST \
130133
-H 'Content-type: application/json' \
131-
-d '{"msg":"Broken links found in the documentation. Please check the logs at '"${LOGS_URL}"'"}' "${{ secrets.DOCS_LINK_SLACK_WEBHOOK }}"
134+
-d '{"text":":warning: *Broken links found in the documentation.*\nPlease check the logs: '"${LOGS_URL}"'"}' "${{ secrets.DOCS_LINK_SLACK_WEBHOOK }}"
135+
echo "Sent Slack notification"
136+
env:
137+
LOGS_URL: https://github.com/coder/coder/actions/runs/${{ github.run_id }}
138+
139+
audit-docs-paths:
140+
runs-on: ubuntu-22.04
141+
permissions:
142+
contents: read
143+
steps:
144+
- name: Harden Runner
145+
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
146+
with:
147+
egress-policy: audit
148+
149+
- name: Checkout
150+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
151+
with:
152+
persist-credentials: false
153+
154+
- name: Check for audit script
155+
id: check-script
156+
run: |
157+
if [ ! -f site/scripts/audit-docs-paths.mjs ]; then
158+
echo "::notice::Audit script not yet available (pending PR #25740). Skipping."
159+
echo "skip=true" >> "$GITHUB_OUTPUT"
160+
fi
161+
162+
- name: Set up mise tools
163+
if: steps.check-script.outputs.skip != 'true'
164+
uses: ./.github/actions/setup-mise
165+
with:
166+
install-args: "node"
167+
168+
- name: Fetch redirects.json
169+
if: steps.check-script.outputs.skip != 'true'
170+
run: |
171+
curl -sfL \
172+
https://raw.githubusercontent.com/coder/coder.com/main/redirects.json \
173+
-o /tmp/redirects.json
174+
175+
- name: Audit TS/TSX docs paths against redirects
176+
if: steps.check-script.outputs.skip != 'true'
177+
run: |
178+
node site/scripts/audit-docs-paths.mjs \
179+
--redirects=/tmp/redirects.json \
180+
--roots=site/src \
181+
--out=/tmp/audit-report.md 2>&1 | tee /tmp/audit-output.txt
182+
183+
count=$(grep -oP 'Total findings: \K\d+' /tmp/audit-output.txt || echo "0")
184+
if [ "$count" -gt 0 ]; then
185+
echo "::error::Found $count stale docs path(s) pointing at redirect sources"
186+
cat /tmp/audit-report.md >> "$GITHUB_STEP_SUMMARY"
187+
exit 1
188+
fi
189+
190+
- name: Send Slack notification
191+
if: failure() && github.event_name != 'pull_request'
192+
run: |
193+
curl \
194+
-X POST \
195+
-H 'Content-type: application/json' \
196+
-d '{"text":":warning: *Stale docs paths found in site/src/.*\nTS/TSX files reference docs URLs that now redirect. Please check the logs: '"${LOGS_URL}"'"}' "${{ secrets.DOCS_LINK_SLACK_WEBHOOK }}"
132197
echo "Sent Slack notification"
133198
env:
134199
LOGS_URL: https://github.com/coder/coder/actions/runs/${{ github.run_id }}

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,9 @@ license.txt
115115

116116
# Agent planning documents (local working files).
117117
docs/plans/
118+
119+
# Local audit reports (e.g. site/scripts/audit-docs-paths.mjs output).
120+
# The file is for local inspection only.
121+
docs/.audit/
122+
118123
/release-action

cli/testdata/coder_server_--help.golden

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,5 +982,9 @@ These options are only available in the Enterprise Edition.
982982
Enables SCIM and sets the authentication header for the built-in SCIM
983983
server. New users are automatically created with OIDC authentication.
984984

985+
--scim-use-legacy bool, $CODER_SCIM_USE_LEGACY (default: true)
986+
Use the legacy SCIM implementation instead of the SCIM 2.0 handler.
987+
This is provided for backward compatibility for existing users.
988+
985989
———
986990
Run `coder --help` for a list of global options.

cli/testdata/server-config.yaml.golden

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,10 @@ sshKeygenAlgorithm: ed25519
519519
# URL to use for agent troubleshooting when not set in the template.
520520
# (default: https://coder.com/docs/admin/templates/troubleshooting, type: url)
521521
agentFallbackTroubleshootingURL: https://coder.com/docs/admin/templates/troubleshooting
522+
# Use the legacy SCIM implementation instead of the SCIM 2.0 handler. This is
523+
# provided for backward compatibility for existing users.
524+
# (default: true, type: bool)
525+
scimUseLegacy: true
522526
# Disable workspace apps that are not served from subdomains. Path-based apps can
523527
# make requests to the Coder API and pose a security risk when the workspace
524528
# serves malicious JavaScript. This is recommended for security purposes if a

coderd/apidoc/docs.go

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/templatebuilder/bases.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type BaseManifest struct {
4141
DisplayName string `json:"display_name"`
4242
OS string `json:"os"`
4343
DefaultContext BaseDefaultContext `json:"default_context"`
44+
Variables []ModuleVariable `json:"variables"`
4445
}
4546

4647
// BaseDefaultContext holds default render values stored in base.json.
@@ -192,6 +193,17 @@ func BaseTemplateIDs() []string {
192193
return ids
193194
}
194195

196+
// BaseVariables returns the user-facing variables for a given base
197+
// template ID. Computed variables are excluded. Returns nil if the
198+
// base is unknown or has no variables.
199+
func BaseVariables(exampleID string) []ModuleVariable {
200+
bases, err := loadBases()
201+
if err != nil || bases[exampleID] == nil {
202+
return nil
203+
}
204+
return bases[exampleID].Manifest.Variables
205+
}
206+
195207
// BaseTemplateFS returns a filesystem rooted at the given base template
196208
// directory within the embedded bases catalog. Returns an error if
197209
// exampleID is not a known base template.

coderd/templatebuilder/bases/kubernetes/base.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,24 @@
44
"os": "linux",
55
"default_context": {
66
"container_image": "codercom/enterprise-base:ubuntu"
7-
}
7+
},
8+
"variables": [
9+
{
10+
"name": "use_kubeconfig",
11+
"type": "bool",
12+
"description": "Use host kubeconfig. Set to true if the Coder host is running outside the Kubernetes cluster for workspaces.",
13+
"default": false,
14+
"required": false,
15+
"sensitive": false,
16+
"computed": false
17+
},
18+
{
19+
"name": "namespace",
20+
"type": "string",
21+
"description": "The Kubernetes namespace to create workspaces in. Must exist prior to creating workspaces.",
22+
"required": true,
23+
"sensitive": false,
24+
"computed": false
25+
}
26+
]
827
}

coderd/templatebuilder/compose.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"archive/tar"
55
"bytes"
66
"encoding/json"
7+
"maps"
78
"regexp"
89
"strings"
910
"time"
@@ -21,6 +22,9 @@ var numberPattern = regexp.MustCompile(`^-?[0-9]+(\.[0-9]+)?$`)
2122
// ComposeRequest describes which base template and modules to render.
2223
type ComposeRequest struct {
2324
BaseTemplateID string
25+
// BaseVariableValues maps base template variable names to their
26+
// user-supplied values.
27+
BaseVariableValues map[string]string
2428
// RegistryURL is the module registry base URL from the deployment
2529
// config (CODER_TEMPLATE_BUILDER_REGISTRY_URL).
2630
RegistryURL string
@@ -49,7 +53,7 @@ type ComposeResult struct {
4953
// source files. It extracts the coder_agent resource name from the
5054
// rendered base HCL and wires it into each module block.
5155
func Compose(req ComposeRequest) (*ComposeResult, error) {
52-
mainTF, err := renderBase(req.BaseTemplateID)
56+
mainTF, err := renderBase(req.BaseTemplateID, req.BaseVariableValues)
5357
if err != nil {
5458
return nil, err
5559
}
@@ -93,9 +97,14 @@ func formatHCL(src []byte) []byte {
9397
return hclwrite.Format(src)
9498
}
9599

96-
// renderBase renders the base template for the given example ID.
97-
func renderBase(baseTemplateID string) ([]byte, error) {
100+
// renderBase renders the base template for the given example ID,
101+
// merging any user-supplied variable values into the render context.
102+
func renderBase(baseTemplateID string, baseVars map[string]string) ([]byte, error) {
98103
renderCtx := DefaultBaseRenderContext(baseTemplateID)
104+
if renderCtx.Variables == nil {
105+
renderCtx.Variables = make(map[string]string)
106+
}
107+
maps.Copy(renderCtx.Variables, baseVars)
99108
mainTF, err := RenderBaseTemplate(baseTemplateID, "main.tf.tmpl", renderCtx)
100109
if err != nil {
101110
return nil, xerrors.Errorf("render base template: %w", err)

coderd/templatebuilder_handler.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,14 @@ func (api *API) templateBuilderBases(rw http.ResponseWriter, r *http.Request) {
7272
slog.F("base_template_id", id))
7373
continue
7474
}
75+
vars := baseVariablesToSDK(templatebuilder.BaseVariables(id))
7576
bases = append(bases, codersdk.TemplateBuilderBase{
7677
ID: ex.ID,
7778
Name: ex.Name,
7879
Description: ex.Description,
7980
Icon: ex.Icon,
8081
OS: string(templatebuilder.BaseTemplateOS(id)),
82+
Variables: vars,
8183
})
8284
}
8385

@@ -90,6 +92,26 @@ func (api *API) templateBuilderBases(rw http.ResponseWriter, r *http.Request) {
9092
})
9193
}
9294

95+
// baseVariablesToSDK converts base template variables to the SDK type,
96+
// filtering out computed variables that the builder wires automatically.
97+
func baseVariablesToSDK(vars []templatebuilder.ModuleVariable) []codersdk.TemplateBuilderModuleVariable {
98+
out := make([]codersdk.TemplateBuilderModuleVariable, 0, len(vars))
99+
for _, v := range vars {
100+
if v.Computed {
101+
continue
102+
}
103+
out = append(out, codersdk.TemplateBuilderModuleVariable{
104+
Name: v.Name,
105+
Type: codersdk.TemplateBuilderVariableType(v.Type),
106+
Description: v.Description,
107+
Default: v.Default,
108+
Required: v.Required,
109+
Sensitive: v.Sensitive,
110+
})
111+
}
112+
return out
113+
}
114+
93115
// @Summary List template builder modules
94116
// @ID list-template-builder-modules
95117
// @Security CoderSessionToken
@@ -171,8 +193,9 @@ func (api *API) templateBuilderCompose(rw http.ResponseWriter, r *http.Request)
171193
}
172194

173195
composeReq := templatebuilder.ComposeRequest{
174-
BaseTemplateID: req.BaseTemplateID,
175-
RegistryURL: api.DeploymentValues.TemplateBuilder.RegistryURL.String(),
196+
BaseTemplateID: req.BaseTemplateID,
197+
BaseVariableValues: req.BaseVariableValues,
198+
RegistryURL: api.DeploymentValues.TemplateBuilder.RegistryURL.String(),
176199
}
177200
for _, m := range req.Modules {
178201
composeReq.Modules = append(composeReq.Modules, templatebuilder.ComposeModule{
@@ -280,8 +303,9 @@ func (api *API) templateBuilderCreateTemplate(rw http.ResponseWriter, r *http.Re
280303

281304
// Compose the template.
282305
composeReq := templatebuilder.ComposeRequest{
283-
BaseTemplateID: req.BaseTemplateID,
284-
RegistryURL: api.DeploymentValues.TemplateBuilder.RegistryURL.String(),
306+
BaseTemplateID: req.BaseTemplateID,
307+
BaseVariableValues: req.BaseVariableValues,
308+
RegistryURL: api.DeploymentValues.TemplateBuilder.RegistryURL.String(),
285309
}
286310
for _, m := range req.Modules {
287311
composeReq.Modules = append(composeReq.Modules, templatebuilder.ComposeModule{

0 commit comments

Comments
 (0)