Skip to content

feat: add coder_script_order data source - #550

Open
BobbyHo wants to merge 3 commits into
mainfrom
bobby/plat-542-phase-1-add-coder_script_order-data-source
Open

BobbyHo wants to merge 3 commits into
mainfrom
bobby/plat-542-phase-1-add-coder_script_order-data-source

Conversation

@BobbyHo

@BobbyHo BobbyHo commented Oct 5, 2026 •

Copy link
Copy Markdown

TL;DR

Coder v2.39 will order startup and shutdown scripts, but templates have no way to declare the order because the Terraform provider does not define the coder_script_order data source. This PR adds it. Template authors can write ordering rules, Terraform checks the basic structure during terraform plan, and Coder v2.39 and later resolves the selectors and validates the rest when the template is imported. Older Coder versions ignore the data source and run scripts in parallel; both descriptions carry the provider's standard version callout.

Replaces draft #536, which predates the phase attribute.

Refs https://linear.app/codercom/issue/PLAT-542

Implementation
  • provider/script_order.go: new data source with one or more rule blocks. Each rule has run and after selector lists, an optional requires that defaults to success, and an optional phase with no default.
  • Validation covers structure and enum values only. Selector strings are passed through unchanged. Coder resolves them against the whole plan, so a stricter check here could reject selectors Coder accepts.
  • phase has no default on purpose. Coder infers the phase when it is unset and warns when inference filtered a module selector. A default would hide both behaviours.
  • SchemaVersion is 0, since this is a new type. feat: add coder_script_order data source #536 used 1.
  • provider/provider.go: registers the data source.
  • examples/data-sources/coder_script_order/data-source.tf: three rules covering defaults, requires = "completion", and an explicit phase.
  • docs/data-sources/script_order.md: generated. The description notes that Terraform does not check selectors, that all values must be known at plan time, and carries the -> ... only available in Coder v2.39 and later. callout.
  • provider/script.go and docs/resources/script.md: the coder_script description now says scripts run in parallel unless a coder_script_order orders them, with the same v2.39 callout.
Expected Output
  • A data source with one or more rules, each with non-empty run and after lists, passes terraform plan. The plan holds every selector exactly as written, requires set to success where omitted, and phase unset where omitted.
  • A data source with no rule block fails with "Insufficient rule blocks".
  • A rule missing run or after fails with "The argument ... is required".
  • run = [] or after = [] fails with "requires 1 item minimum".
  • An empty string inside run or after fails with "to not be an empty string", naming the index.
  • requires other than success or completion fails, including an explicit empty string. The match is case-sensitive.
  • phase other than start or stop fails. The match is case-sensitive.
  • Selectors that are not valid or not supported Terraform addresses are accepted by the provider and stored unchanged. Coder reports them at template import.
  • The read has no side effects and needs no provider configuration.
  • The plan JSON uses exactly the attribute names rule, run, after, requires and phase, which is what Coder's provisioner decodes.
Testing
  • TestScriptOrder plans four rules and asserts twenty state attributes: list lengths and items, the requires default, phase staying empty when omitted, an indexed selector, a module selector, and an invalid selector passed through unchanged.
  • TestScriptOrderValidation has eleven rejection cases with the exact Terraform error for each: no rules, missing run or after, empty lists, empty selector strings, invalid requires, empty requires, invalid phase, and wrong-case phase.
  • TestScriptOrderContract reads the schema and pins the attribute names Coder decodes, the requires default, and the absence of a phase default.
  • TestExamples now plans the new example file.
  • Every bullet in Expected Output is covered. The requires = "" case pins what the SDK does today (rejection) so an SDK upgrade cannot change it unnoticed.
  • go test ./provider/ passes (full suite, 48s).
Manual Test

Run on a laptop against this branch at a35da93, Terraform v1.15.7, provider built with make build and wired in through a dev_overrides entry in ~/.terraformrc. No Coder deployment is involved: the data source is evaluated entirely by Terraform during plan, so everything this PR adds is visible in terraform show -json and terraform validate. All 22 scenarios passed. No product defects found.

# Scenario Result
1 Build from the branch, point Terraform at the local binary, confirm the override is used Pass
2 Schema Terraform sees: rule (min 1) with run, after required, requires, phase optional Pass
3 Minimal rule: requires defaults to success, phase left unset Pass
4 Four rules covering omitted, default and explicit values; nothing reordered or trimmed Pass
5 Six selectors the provider cannot judge are passed through unchanged Pass
6 dynamic "rule" with format() expands into plain rules Pass
7 count = 0 on the data source removes it; count = 1 gives an indexed address Pass
8 A data source inside a child module keeps the module path in its address Pass
9 No rule block is rejected Pass
10 Missing run is rejected Pass
11 after = [] is rejected Pass
12 Empty string inside a list is rejected, naming the index Pass
13 requires = "always" is rejected Pass
14 requires = "" is rejected, by both validate and plan Pass
15 phase = "both" is rejected Pass
16 phase = "Start" is rejected (case-sensitive) Pass
17 Whitespace-only selector " " is accepted; rejecting it is Coder's job Pass
18 Plan JSON keys are exactly after, phase, requires, run Pass
19 An unset phase serializes as "", not null Pass
20 make gen produces no diff against the committed docs Pass
21 Full go test ./provider/ passes Pass
22 Cleanup: scratch files, binary and the dev_overrides line removed Pass

Two facts worth knowing from the run:

  • Terraform 1.15 records a data source read during plan under prior_state.values, not planned_values. The commands below read from there.
  • An unset phase comes through as the empty string. Coder treats "" as "infer the phase", so this is the form the Coder-side fixtures should expect.
Shell helpers used throughout
# $1 = case directory. Writes the provider header, appends stdin, plans,
# and prints every coder_script_order in the plan JSON.
tfplan() {
  local dir="/tmp/plat542/$1"
  mkdir -p "$dir" && cd "$dir" || return 1
  {
    printf 'terraform {\n  required_providers {\n    coder = { source = "coder/coder" }\n  }\n}\nprovider "coder" {}\n\n'
    cat
  } > main.tf
  terraform plan -out=tfplan -input=false >/tmp/plat542/last-plan.txt 2>&1 \
    || { echo "PLAN FAILED"; cat /tmp/plat542/last-plan.txt; return 1; }
  terraform show -json tfplan \
    | jq '[.prior_state.values.root_module
            | .. | objects | select(.type? == "coder_script_order")
            | {address, values}]'
}

# Same header, runs validate, prints only the error lines.
tfreject() {
  local dir="/tmp/plat542/$1"
  mkdir -p "$dir" && cd "$dir" || return 1
  {
    printf 'terraform {\n  required_providers {\n    coder = { source = "coder/coder" }\n  }\n}\nprovider "coder" {}\n\n'
    cat
  } > main.tf
  terraform validate -no-color 2>&1 | grep -E '^Error|^│ |requires|expected|Insufficient|required' | sed 's/^│ //'
}
1. Build and dev override
cd ~/work/terraform-provider-coder
git status --porcelain && git branch --show-current && git log -1 --format=%h
make build && ls -la terraform-provider-coder
bobby/plat-542-phase-1-add-coder_script_order-data-source
a35da93
CGO_ENABLED=0 go build .
-rwxr-xr-x  1 bobbyho  staff  27323026 Oct  5 11:33 terraform-provider-coder

~/.terraformrc:

provider_installation {
  dev_overrides {
    "coder/coder" = "/Users/bobbyho/work/terraform-provider-coder"
  }
  direct {}
}
mkdir -p /tmp/plat542/init && cd /tmp/plat542/init
cat > main.tf <<'EOF'
terraform {
  required_providers {
    coder = { source = "coder/coder" }
  }
}
provider "coder" {}
EOF
terraform init
Warning: Provider development overrides are in effect

The following provider development overrides are set in the CLI
configuration:
 - coder/coder in /Users/bobbyho/work/terraform-provider-coder

These providers are not installed as part of init since they were
overwritten.

No .terraform/ or lock file was created; nothing was downloaded.

2. Schema Terraform sees
cd /tmp/plat542/init
terraform providers schema -json \
  | jq '.provider_schemas["registry.terraform.io/coder/coder"].data_source_schemas.coder_script_order.block
        | {attrs: (.attributes | keys), rule_min: .block_types.rule.min_items,
           rule_attrs: (.block_types.rule.block.attributes | to_entries
             | map({key, required: .value.required, optional: .value.optional}))}'
{
  "attrs": ["id"],
  "rule_min": 1,
  "rule_attrs": [
    {"key": "after",    "required": true,  "optional": null},
    {"key": "phase",    "required": null,  "optional": true},
    {"key": "requires", "required": null,  "optional": true},
    {"key": "run",      "required": true,  "optional": null}
  ]
}
3. Minimal rule
tfplan 1a-minimal <<'EOF'
data "coder_script_order" "bootstrap" {
  rule {
    run   = ["coder_script.install_tools"]
    after = ["coder_script.clone_repo"]
  }
}
EOF
[{
  "address": "data.coder_script_order.bootstrap",
  "values": {
    "id": "7d914bf5-15c5-441c-aed0-6e44893ae00b",
    "rule": [
      {"after": ["coder_script.clone_repo"], "phase": "", "requires": "success", "run": ["coder_script.install_tools"]}
    ]
  }
}]
4. Four rules covering every attribute state
tfplan 1b-four-rules <<'EOF' | jq -c '.[0].values.rule[]'
data "coder_script_order" "startup" {
  rule {
    run   = ["coder_script.install_tools", "coder_script.configure_shell"]
    after = ["coder_script.clone_repo", "coder_script.authenticate"]
  }
  rule {
    run      = ["coder_script.setup[\"api\"]"]
    after    = ["module.bootstrap"]
    requires = "completion"
  }
  rule {
    run   = ["module.application"]
    after = ["module.checkout"]
    phase = "stop"
  }
  rule {
    run   = ["not valid selector syntax"]
    after = ["also not valid"]
  }
}
EOF
{"after":["coder_script.clone_repo","coder_script.authenticate"],"phase":"","requires":"success","run":["coder_script.install_tools","coder_script.configure_shell"]}
{"after":["module.bootstrap"],"phase":"","requires":"completion","run":["coder_script.setup[\"api\"]"]}
{"after":["module.checkout"],"phase":"stop","requires":"success","run":["module.application"]}
{"after":["also not valid"],"phase":"","requires":"success","run":["not valid selector syntax"]}
5. Selectors the provider cannot judge are passed through
tfplan 1c-opaque <<'EOF' | jq -c '.[0].values.rule[0]'
data "coder_script_order" "x" {
  rule {
    run   = ["coder_agent.main", "coder_script.*", "module.a.coder_script.b"]
    after = ["module.git_clone[0]", "data.coder_script.x", "coder_script.clone_rpo"]
  }
}
EOF
{"after":["module.git_clone[0]","data.coder_script.x","coder_script.clone_rpo"],"phase":"","requires":"success","run":["coder_agent.main","coder_script.*","module.a.coder_script.b"]}

Every one of these is rejected by Coder at template import. The provider accepting them is intended: it has no view of the rest of the template, and a stricter check here could reject selectors Coder accepts.

6. dynamic rule block with format()
tfplan 1d-dynamic <<'EOF' | jq -c '.[0].values.rule[]'
locals {
  services = toset(["api", "worker"])
}

data "coder_script_order" "per_service" {
  dynamic "rule" {
    for_each = local.services
    content {
      run   = [format("coder_script.install[%q]", rule.key)]
      after = [format("coder_script.clone[%q]", rule.key)]
    }
  }
}
EOF
{"after":["coder_script.clone[\"api\"]"],"phase":"","requires":"success","run":["coder_script.install[\"api\"]"]}
{"after":["coder_script.clone[\"worker\"]"],"phase":"","requires":"success","run":["coder_script.install[\"worker\"]"]}
7. count on the data source
tfplan 1e-count-zero <<'EOF'
variable "enable_ordering" {
  default = false
}

data "coder_script_order" "optional" {
  count = var.enable_ordering ? 1 : 0
  rule {
    run   = ["coder_script.a"]
    after = ["coder_script.b"]
  }
}
EOF
[]
cd /tmp/plat542/1e-count-zero
terraform plan -out=tfplan -input=false -var enable_ordering=true >/dev/null \
  && terraform show -json tfplan | jq -c '[.prior_state.values.root_module.resources[] | select(.type=="coder_script_order") | {address, rule: .values.rule[0]}]'
[{"address":"data.coder_script_order.optional[0]","rule":{"after":["coder_script.b"],"phase":"","requires":"success","run":["coder_script.a"]}}]
8. Data source inside a child module
mkdir -p /tmp/plat542/1f-module/mod
cat > /tmp/plat542/1f-module/mod/main.tf <<'EOF'
terraform {
  required_providers {
    coder = { source = "coder/coder" }
  }
}
data "coder_script_order" "internal" {
  rule {
    run   = ["coder_script.configure_git"]
    after = ["coder_script.clone"]
  }
}
EOF

tfplan 1f-module <<'EOF'
module "git_clone" {
  source = "./mod"
}

data "coder_script_order" "repo" {
  rule {
    run   = ["coder_script.install_tools"]
    after = ["module.git_clone"]
  }
}
EOF
# first run: "Error: Module not installed"; ran terraform init in the directory, then:
cd /tmp/plat542/1f-module && terraform plan -out=tfplan -input=false >/dev/null \
  && terraform show -json tfplan | jq -c '[.prior_state.values.root_module | .. | objects | select(.type? == "coder_script_order") | {address, rule: .values.rule[0]}] | .[]'
{"address":"data.coder_script_order.repo","rule":{"after":["module.git_clone"],"phase":"","requires":"success","run":["coder_script.install_tools"]}}
{"address":"module.git_clone.data.coder_script_order.internal","rule":{"after":["coder_script.clone"],"phase":"","requires":"success","run":["coder_script.configure_git"]}}
9. No rule block
tfreject 2a-no-rule <<'EOF'
data "coder_script_order" "x" {}
EOF
Error: Insufficient rule blocks

  on main.tf line 8, in data "coder_script_order" "x":
   8: data "coder_script_order" "x" {}

At least 1 "rule" blocks are required.
10. Missing run
tfreject 2b-missing-run <<'EOF'
data "coder_script_order" "x" {
  rule {
    after = ["coder_script.clone_repo"]
  }
}
EOF
Error: Missing required argument

  on main.tf line 9, in data "coder_script_order" "x":
   9:   rule {

The argument "run" is required, but no definition was found.
11. Empty after list
tfreject 2c-empty-after <<'EOF'
data "coder_script_order" "x" {
  rule {
    run   = ["coder_script.install_tools"]
    after = []
  }
}
EOF
Error: Not enough list items

  with data.coder_script_order.x,
  on main.tf line 11, in data "coder_script_order" "x":
  11:     after = []

Attribute rule.0.after requires 1 item minimum, but config has only 0 declared.
12. Empty string inside a list
tfreject 2d-empty-string <<'EOF'
data "coder_script_order" "x" {
  rule {
    run   = ["coder_script.a", ""]
    after = ["coder_script.b"]
  }
}
EOF
Error: expected "rule.0.run.1" to not be an empty string, got 

  with data.coder_script_order.x,
  on main.tf line 10, in data "coder_script_order" "x":
  10:     run   = ["coder_script.a", ""]
13. Unknown requires
tfreject 2e-bad-requires <<'EOF'
data "coder_script_order" "x" {
  rule {
    run      = ["coder_script.a"]
    after    = ["coder_script.b"]
    requires = "always"
  }
}
EOF
Error: expected rule.0.requires to be one of ["success" "completion"], got always

  with data.coder_script_order.x,
  on main.tf line 12, in data "coder_script_order" "x":
  12:     requires = "always"
14. Explicit empty requires
tfreject 2f-empty-requires <<'EOF'
data "coder_script_order" "x" {
  rule {
    run      = ["coder_script.a"]
    after    = ["coder_script.b"]
    requires = ""
  }
}
EOF
cd /tmp/plat542/2f-empty-requires && terraform plan -out=tfplan -input=false
Error: expected rule.0.requires to be one of ["success" "completion"], got 

  with data.coder_script_order.x,
  on main.tf line 12, in data "coder_script_order" "x":
  12:     requires = ""

Both validate and plan reject it. The default applies only when the attribute is absent; a present empty string goes to the validator. This agrees with the EmptyRequires unit test.

15. Unknown phase
tfreject 2g-bad-phase <<'EOF'
data "coder_script_order" "x" {
  rule {
    run   = ["coder_script.a"]
    after = ["coder_script.b"]
    phase = "both"
  }
}
EOF
Error: expected rule.0.phase to be one of ["start" "stop"], got both

  with data.coder_script_order.x,
  on main.tf line 12, in data "coder_script_order" "x":
  12:     phase = "both"
16. Wrong-case phase
tfreject 2h-phase-case <<'EOF'
data "coder_script_order" "x" {
  rule {
    run   = ["coder_script.a"]
    after = ["coder_script.b"]
    phase = "Start"
  }
}
EOF
Error: expected rule.0.phase to be one of ["start" "stop"], got Start

  with data.coder_script_order.x,
  on main.tf line 12, in data "coder_script_order" "x":
  12:     phase = "Start"
17. Whitespace-only selector is accepted
tfplan 2i-whitespace <<'EOF' | jq -c '.[0].values.rule[0], (.[0].values.rule[0].run[0] | length)'
data "coder_script_order" "x" {
  rule {
    run   = [" "]
    after = ["coder_script.b"]
  }
}
EOF
{"after":["coder_script.b"],"phase":"","requires":"success","run":[" "]}
1

The check is "not empty", matching the RFC. Coder rejects " " at import as invalid address syntax.

18. Attribute names in the plan JSON
cd /tmp/plat542/1b-four-rules
terraform show -json tfplan \
  | jq -c '.prior_state.values.root_module.resources[]
           | select(.type=="coder_script_order")
           | {top: (.values | keys), rule: (.values.rule[0] | keys), all_rules_same_keys: ([.values.rule[] | keys] | unique | length)}'
{"top":["id","rule"],"rule":["after","phase","requires","run"],"all_rules_same_keys":1}

These are the names Coder's provisioner decodes. Every rule carries the same key set, so an omitted attribute still appears as a key with its default or empty value.

19. How an unset phase is serialized
cd /tmp/plat542/1a-minimal
terraform show -json tfplan \
  | jq -c '.prior_state.values.root_module.resources[]
           | select(.type=="coder_script_order")
           | .values.rule[0] | {phase, phase_type: (.phase | type)}'
cd /tmp/plat542/1b-four-rules
terraform show -json tfplan \
  | jq -c '[.prior_state.values.root_module.resources[] | select(.type=="coder_script_order") | .values.rule[] | .phase | type] | unique'
{"phase":"","phase_type":"string"}
["string"]
20. Docs regenerate cleanly
cd ~/work/terraform-provider-coder
make gen >/dev/null 2>&1; echo "gen exit=$?"
git status --porcelain; echo "status lines=$(git status --porcelain | wc -l | tr -d ' ')"
gen exit=0
status lines=0
21. Full provider test suite
cd ~/work/terraform-provider-coder
go test ./provider/ -count=1
ok  	github.com/coder/terraform-provider-coder/v2/provider	47.973s
22. Cleanup
rm -rf /tmp/plat542
cd ~/work/terraform-provider-coder && rm -f terraform-provider-coder && git status --porcelain
# removed the "coder/coder" line from ~/.terraformrc
cat ~/.terraformrc
provider_installation {
  dev_overrides {
    "coder/coderd" = "/Users/bobbyho/go/bin"
  }
  direct {}
}

git status printed nothing. Terraform on the laptop uses the released provider again.

Templates have no way to declare script ordering because the provider
does not define the data source Coder already reads. This adds it.

- New data source with one or more rule blocks. Each rule has run and
  after selector lists, an optional requires (default success) and an
  optional phase (start or stop, no default).
- Validation covers structure and enum values only: at least one rule,
  at least one item in each list, no empty strings, requires in
  {success, completion}, phase in {start, stop}. Selector strings are
  passed through unchanged for Coder to resolve after plan.
- phase has no default on purpose. Coder infers the phase when it is
  unset and warns when inference filtered a module selector. A default
  would hide both.
- Tests: schema test over four rules, eleven rejection cases, and a
  test that pins the attribute names Coder decodes from the plan JSON.
- Example and generated docs. The description notes that Terraform does
  not check selectors, that values must be known at plan time, and that
  older Coder versions ignore the data source.
- coder_script description now says scripts run in parallel unless a
  coder_script_order orders them.

Replaces draft #536, which predates the phase attribute.

Refs https://linear.app/codercom/issue/PLAT-542
@linear-code

linear-code Bot commented Oct 5, 2026

Copy link
Copy Markdown

PLAT-542

@BobbyHo

BobbyHo commented Oct 5, 2026

Copy link
Copy Markdown
Author

/coder-agents-review Please limit the review to P0, P1, P2 and P3 issues only.

@BobbyHo
BobbyHo marked this pull request as ready for review October 5, 2026 19:37
@BobbyHo
BobbyHo requested a review from geokat October 5, 2026 19:38
@BobbyHo

BobbyHo commented Oct 6, 2026

Copy link
Copy Markdown
Author

/coder-agents-review Please limit the review to P0, P1, P2 and P3 issues only.

@coder-agents-review

coder-agents-review Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Chat: Review posted | View chat
Requested: 2026-10-06 14:55 UTC by @BobbyHo

Review history
  • R1 (2026-10-06): 9 reviewers, 1 P2, 2 P3, COMMENT. Review

deep-review v0.13.0 | Round 1 | 97991e3..a35da93

Last posted: Round 1, 3 findings (1 P2, 2 P3), COMMENT. Review

Finding inventory

Finding inventory: PR #550

Findings

# Sev Status Location Summary Round Reviewer Posted
CRF-1 P2 Open provider/script_order.go:52 Docs state Coder enforces ordering and checks selectors at import, but no Coder version consumes the data source and no minimum version is named; same claim in script.go:47, commit body, PR TL;DR R1 Pariston P1, Melody P2, Mafuuu P2, Kite P2/P3, Leorio P3 Yes
CRF-2 P3 Open provider/script_order.go:82 phase description says omitting phase only costs a warning; Coder rejects module-only rules spanning both phases R1 Pariston, Leorio Yes
CRF-3 P3 Open provider/script_order.go:67 after description "they" has no antecedent because tfplugindocs lists after before run R1 Gon, Leorio Yes
CRF-4 Nit Dropped by orchestrator (below P3, author asked for P0-P3 only) provider/script_order.go:23 Selector comment repeats the Description R1 Gon No
CRF-5 Nit Dropped by orchestrator (below P3, author asked for P0-P3 only) provider/script_order.go:12 Const block comment "the same values" is vague and repeats the test comment R1 Gon No
CRF-6 Nit Dropped by orchestrator (below P3, author asked for P0-P3 only) provider/script_order_test.go:173 EmptyRequires comment states its purpose twice R1 Gon No
CRF-7 Note Dropped by orchestrator (below P3, author asked for P0-P3 only) provider/script_order.go:61 "one graph per agent" vs Coder's one graph per runtime and phase R1 Melody No
CRF-8 Note Dropped by orchestrator (below P3, author asked for P0-P3 only) provider/script_order_test.go:229 Comment cites a coder/coder file that open PR #30337 moves R1 Netero No
CRF-9 OOS Out of scope (body) coder/coder provisioner/terraform/scriptorder.go:754 resolveScriptOrder has no non-test caller on coder/coder main R1 Pariston, Melody, Mafuuu, Kite, Leorio No

Contested and acknowledged

None.

Round log

Round 1

Netero: no findings, one Note. Panel (round 1, full): ging-go, ryosuke, melody, pariston, mafuuu, bisky, gon, leorio, kite (wildcard). 1 P2, 2 P3 posted. 3 Nit and 2 Note dropped per the author's P0-P3 request. 1 out of scope. CRF-1 set to P2 over Pariston's P1: keep-argument for P1 is that every deployment silently ignores the rules, including requires = "success"; P2 because the description already says unsupported versions ignore the data source, and the harm needs a provider release before Coder ships, which the fix (name the version or hold the release) addresses. Orchestrator verified on coder/coder main 9ce4f2f358 that resolveScriptOrder has no non-test caller and that determineScriptOrderRulePhase errors for module-only mixed-phase rules. Reviewed against 97991e3..a35da93.

About deep-review

CRF = Coder Review Finding (P0-P4, Nit, Note)

Reviewer Focus
Bisky tests
Chopper ops/errors
Churn-guard change verification
Ging language modernization
Gon naming
Hisoka edge cases
Killua perf
Kite change integrity
Knov contracts
Knuckle SQL
Komugi flake/determinism
Kurapika security
Law decomposition
Leorio docs
Luffy product
Mafu-san process
Mafuuu contracts
Melody dispatch/pairing
Meruem structural
Nami frontend
Netero mechanical checks
Pariston premise testing
Pen-botter product gaps
Razor verification
Robin duplication
Ryosuke Go arch
Takumi concurrency
Zoro shape

🤖 Managed by Coder Agents.

@coder-agents-review coder-agents-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR adds the coder_script_order data source, its docs and example, and tests that pin its schema. Findings: 1 P2, 2 P3. Per your request, findings below P3 are not posted.

Out of scope (needs a ticket or explicit acceptance by a human):

  • coder/coder provisioner/terraform/scriptorder.go:754: resolveScriptOrder has no non-test caller on coder/coder main (9ce4f2f358), so no Coder build decodes coder_script_order at template import or orders scripts in the agent. Until that lands, a released provider exposes a data source that no deployment acts on.

🤖 This review was automatically generated with Coder Agents.

Comment thread provider/script_order.go Outdated
Comment thread provider/script_order.go
Comment thread provider/script_order.go Outdated
Both descriptions now use the provider's standard callout form and
name Coder v2.39 as the first version that orders scripts. Older
versions ignore the data source.
run and after each name the other attribute so the generated page
reads correctly in alphabetical order. The phase description now says
Coder rejects a module-only rule that spans both phases instead of
implying omission always works.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant