Skip to content

Commit 1d3c04f

Browse files
committed
get initial version of parsing working
1 parent db2fd0e commit 1d3c04f

File tree

4 files changed

+175
-40
lines changed

4 files changed

+175
-40
lines changed

cmd/readmevalidation/coderResources.go

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func validateCoderResourceTags(tags []string) error {
114114
// parse any Terraform code snippets, and make some deeper guarantees about how
115115
// it's structured. Just validating whether it *can* be parsed as Terraform
116116
// would be a big improvement.
117-
var terraformVersionRe = regexp.MustCompile("^\\bversion\\s+=")
117+
var terraformVersionRe = regexp.MustCompile("^\\s*\\bversion\\s+=")
118118

119119
func validateCoderResourceReadmeBody(body string) []error {
120120
trimmed := strings.TrimSpace(body)
@@ -137,50 +137,39 @@ func validateCoderResourceReadmeBody(body string) []error {
137137
// Code assumes that invalid headers would've already been handled by
138138
// the base validation function, so we don't need to check deeper if the
139139
// first line isn't an h1
140-
if lineNum == 1 && !strings.HasPrefix(nextLine, "# ") {
141-
break
142-
}
143-
144-
if nextLine == "```" {
145-
if !isInsideCodeBlock {
146-
errs = append(errs, errors.New("found stray ``` (either an extra code block terminator, or a code block header without a specified language)"))
140+
if lineNum == 1 {
141+
if !strings.HasPrefix(nextLine, "# ") {
147142
break
143+
} else {
144+
continue
148145
}
149-
150-
isInsideCodeBlock = false
151-
isInsideTerraform = false
152-
continue
153146
}
154147

155-
if isInsideTerraform {
156-
foundTerraformVersionRef = foundTerraformVersionRef || terraformVersionRe.MatchString(nextLine)
157-
continue
158-
}
159-
if isInsideCodeBlock {
160-
continue
161-
}
162-
163-
// Code assumes that we can treat this case as the end of the "h1
164-
// section" and don't need to process any further lines
165-
if strings.HasPrefix(nextLine, "#") {
166-
break
167-
}
168-
169-
// This is meant to catch cases like ```tf, ```hcl, and ```js
170148
if strings.HasPrefix(nextLine, "```") {
171-
isInsideCodeBlock = true
172-
isInsideTerraform = strings.HasPrefix(nextLine, "```tf")
149+
isInsideCodeBlock = !isInsideCodeBlock
150+
isInsideTerraform = isInsideCodeBlock && strings.HasPrefix(nextLine, "```tf")
173151
if isInsideTerraform {
174152
terraformCodeBlockCount++
175153
}
176-
177154
if strings.HasPrefix(nextLine, "```hcl") {
178155
errs = append(errs, errors.New("all .hcl language references must be converted to .tf"))
179156
}
157+
continue
158+
}
180159

160+
if isInsideCodeBlock {
161+
if isInsideTerraform {
162+
foundTerraformVersionRef = foundTerraformVersionRef || terraformVersionRe.MatchString(nextLine)
163+
}
181164
continue
182165
}
183166

167+
// Code assumes that we can treat this case as the end of the "h1
168+
// section" and don't need to process any further lines
169+
if lineNum > 1 && strings.HasPrefix(nextLine, "#") {
170+
break
171+
}
172+
184173
// Code assumes that if we've reached this point, the only other options
185174
// are: (1) empty spaces, (2) paragraphs, (3) HTML, and (4) asset
186175
// references made via [] syntax
@@ -202,6 +191,9 @@ func validateCoderResourceReadmeBody(body string) []error {
202191
if !foundParagraph {
203192
errs = append(errs, errors.New("did not find paragraph within h1 section"))
204193
}
194+
if isInsideCodeBlock {
195+
errs = append(errs, errors.New("code blocks inside h1 section do not all terminate before end of file"))
196+
}
205197

206198
return errs
207199
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package main
2+
3+
import (
4+
_ "embed"
5+
"testing"
6+
)
7+
8+
//go:embed testSamples/sampleReadmeBody.md
9+
var testBody string
10+
11+
func TestValidateCoderResourceReadmeBody(t *testing.T) {
12+
t.Parallel()
13+
14+
t.Run("Parses a valid README body with zero issues", func(t *testing.T) {
15+
t.Parallel()
16+
17+
errs := validateCoderResourceReadmeBody(testBody)
18+
for _, e := range errs {
19+
t.Error(e)
20+
}
21+
})
22+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Goose
2+
3+
Run the [Goose](https://block.github.io/goose/) agent in your workspace to generate code and perform tasks.
4+
5+
```tf
6+
module "goose" {
7+
source = "registry.coder.com/modules/goose/coder"
8+
version = "1.0.31"
9+
agent_id = coder_agent.example.id
10+
folder = "/home/coder"
11+
install_goose = true
12+
goose_version = "v1.0.16"
13+
}
14+
```
15+
16+
## Prerequisites
17+
18+
- `screen` must be installed in your workspace to run Goose in the background
19+
- You must add the [Coder Login](https://registry.coder.com/modules/coder-login) module to your template
20+
21+
The `codercom/oss-dogfood:latest` container image can be used for testing on container-based workspaces.
22+
23+
## Examples
24+
25+
Your workspace must have `screen` installed to use this.
26+
27+
### Run in the background and report tasks (Experimental)
28+
29+
> This functionality is in early access as of Coder v2.21 and is still evolving.
30+
> For now, we recommend testing it in a demo or staging environment,
31+
> rather than deploying to production
32+
>
33+
> Learn more in [the Coder documentation](https://coder.com/docs/tutorials/ai-agents)
34+
>
35+
> Join our [Discord channel](https://discord.gg/coder) or
36+
> [contact us](https://coder.com/contact) to get help or share feedback.
37+
38+
```tf
39+
module "coder-login" {
40+
count = data.coder_workspace.me.start_count
41+
source = "registry.coder.com/modules/coder-login/coder"
42+
version = "1.0.15"
43+
agent_id = coder_agent.example.id
44+
}
45+
46+
variable "anthropic_api_key" {
47+
type = string
48+
description = "The Anthropic API key"
49+
sensitive = true
50+
}
51+
52+
data "coder_parameter" "ai_prompt" {
53+
type = "string"
54+
name = "AI Prompt"
55+
default = ""
56+
description = "Write a prompt for Goose"
57+
mutable = true
58+
}
59+
60+
# Set the prompt and system prompt for Goose via environment variables
61+
resource "coder_agent" "main" {
62+
# ...
63+
env = {
64+
GOOSE_SYSTEM_PROMPT = <<-EOT
65+
You are a helpful assistant that can help write code.
66+
67+
Run all long running tasks (e.g. npm run dev) in the background and not in the foreground.
68+
69+
Periodically check in on background tasks.
70+
71+
Notify Coder of the status of the task before and after your steps.
72+
EOT
73+
GOOSE_TASK_PROMPT = data.coder_parameter.ai_prompt.value
74+
75+
# An API key is required for experiment_auto_configure
76+
# See https://block.github.io/goose/docs/getting-started/providers
77+
ANTHROPIC_API_KEY = var.anthropic_api_key # or use a coder_parameter
78+
}
79+
}
80+
81+
module "goose" {
82+
count = data.coder_workspace.me.start_count
83+
source = "registry.coder.com/modules/goose/coder"
84+
version = "1.0.31"
85+
agent_id = coder_agent.example.id
86+
folder = "/home/coder"
87+
install_goose = true
88+
goose_version = "v1.0.16"
89+
90+
# Enable experimental features
91+
experiment_report_tasks = true
92+
93+
# Run Goose in the background
94+
experiment_use_screen = true
95+
96+
# Avoid configuring Goose manually
97+
experiment_auto_configure = true
98+
99+
# Required for experiment_auto_configure
100+
experiment_goose_provider = "anthropic"
101+
experiment_goose_model = "claude-3-5-sonnet-latest"
102+
}
103+
```
104+
105+
## Run standalone
106+
107+
Run Goose as a standalone app in your workspace. This will install Goose and run it directly without using screen or any task reporting to the Coder UI.
108+
109+
```tf
110+
module "goose" {
111+
source = "registry.coder.com/modules/goose/coder"
112+
version = "1.0.31"
113+
agent_id = coder_agent.example.id
114+
folder = "/home/coder"
115+
install_goose = true
116+
goose_version = "v1.0.16"
117+
118+
# Icon is not available in Coder v2.20 and below, so we'll use a custom icon URL
119+
icon = "https://raw.githubusercontent.com/block/goose/refs/heads/main/ui/desktop/src/images/icon.svg"
120+
}
121+
```

registry/coder/modules/slackme/README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ tags: [helper]
1111

1212
Add the `slackme` command to your workspace that DMs you on Slack when your command finishes running.
1313

14+
```tf
15+
module "slackme" {
16+
count = data.coder_workspace.me.start_count
17+
source = "registry.coder.com/modules/slackme/coder"
18+
version = "1.0.2"
19+
agent_id = coder_agent.example.id
20+
auth_provider_id = "slack"
21+
}
22+
```
23+
1424
```bash
1525
slackme npm run long-build
1626
```
@@ -54,16 +64,6 @@ slackme npm run long-build
5464

5565
3. Restart your Coder deployment. Any Template can now import the Slack Me module, and `slackme` will be available on the `$PATH`:
5666

57-
```tf
58-
module "slackme" {
59-
count = data.coder_workspace.me.start_count
60-
source = "registry.coder.com/modules/slackme/coder"
61-
version = "1.0.2"
62-
agent_id = coder_agent.example.id
63-
auth_provider_id = "slack"
64-
}
65-
```
66-
6767
## Examples
6868

6969
### Custom Slack Message

0 commit comments

Comments
 (0)