Skip to content

Commit 0f9ea7c

Browse files
fix(quickstart): preserve legacy env layouts
1 parent 68972de commit 0f9ea7c

9 files changed

Lines changed: 364 additions & 102 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Earlier entries pre-date this convention and only carry their version's compare
2626

2727
### Fixed
2828

29-
- Align Python and Go quickstart env writing with the upstream repositories by targeting `server/.env.local` and `AGORA_APP_ID` / `AGORA_APP_CERTIFICATE`, and avoid detecting Go quickstarts as Python quickstarts.
29+
- Align new Python and Go quickstart env writing with the upstream repositories by targeting `server/.env.local` and `AGORA_APP_ID` / `AGORA_APP_CERTIFICATE`, avoid detecting Go quickstarts as Python quickstarts, and retain compatibility with legacy quickstart env layouts.
3030
- Correct the Go skills and README quickstart wording from a token-service recipe to the actual Go ConvoAI voice-agent quickstart.
3131

3232
## [0.2.5] - 2026-06-05

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ Quickstart template behavior:
214214
- Next.js quickstarts write `.env.local` with `NEXT_PUBLIC_AGORA_APP_ID` plus `NEXT_AGORA_APP_CERTIFICATE`
215215
- Python quickstarts copy `server/.env.example` to `server/.env.local`, then use `AGORA_APP_ID` plus `AGORA_APP_CERTIFICATE`
216216
- Go quickstarts copy `server/.env.example` to `server/.env.local`, then use `AGORA_APP_ID` plus `AGORA_APP_CERTIFICATE`
217+
- Existing Python and Go quickstarts keep their recorded env path and legacy `APP_ID` / `APP_CERTIFICATE` keys when reconfigured.
217218

218219
`project env write` auto-detects Next.js workspaces (or accepts `--template nextjs|standard`) and writes `AGORA_APP_ID` / `AGORA_APP_CERTIFICATE` or the Next.js equivalents. Use `quickstart env write` when you want the CLI to choose the official quickstart's env path.
219220

docs/automation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ Env write behavior:
682682
- quickstart env files contain only the App ID and App Certificate variable names required by the template
683683
- Next.js uses `NEXT_PUBLIC_AGORA_APP_ID` and `NEXT_AGORA_APP_CERTIFICATE`
684684
- Python and Go use `AGORA_APP_ID` and `AGORA_APP_CERTIFICATE`
685+
- existing Python and Go quickstarts retain their recorded env path and legacy `APP_ID` / `APP_CERTIFICATE` keys when reconfigured
685686
- project metadata such as project ID, project name, region, template, projectType, and env path is stored in `.agora/project.json`
686687
- existing quickstart env files are preserved; missing credential keys are appended and existing credential keys are updated
687688
- stale Agora credential aliases for another runtime are commented out to avoid ambiguous dotenv resolution; for example, a Next.js quickstart prefers `NEXT_PUBLIC_AGORA_APP_ID` and comments out old `AGORA_APP_ID` / `APP_ID` entries when replacing them

internal/cli/doctor.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,6 @@ func summarizeCategoryStatus(items []doctorCheckItem) string {
4646
return "skipped"
4747
}
4848

49-
func quickstartAppIDKey(templateID string) string {
50-
switch templateID {
51-
case "nextjs":
52-
return "NEXT_PUBLIC_AGORA_APP_ID"
53-
case "python", "go":
54-
return "AGORA_APP_ID"
55-
default:
56-
return ""
57-
}
58-
}
59-
6049
func lookupDotenvValue(content, key string) (string, bool) {
6150
for _, line := range strings.Split(content, "\n") {
6251
trimmed := strings.TrimSpace(line)
@@ -196,8 +185,21 @@ func buildWorkspaceDoctorDetails(target projectTarget) (doctorCheckCategory, map
196185

197186
template, found := findQuickstartTemplate(templateID)
198187
envRel := strings.TrimSpace(binding.EnvPath)
188+
layout := quickstartEnvLayout{}
199189
if found {
200-
envRel = template.EnvTargetPath
190+
if envRel != "" {
191+
layout, _ = quickstartEnvLayoutForEnvPath(*template, envRel)
192+
}
193+
if layout.EnvTargetPath == "" {
194+
if detected, ok := quickstartEnvLayoutForPath(root, *template); ok {
195+
layout = detected
196+
} else if fallback, ok := template.defaultEnvLayout(); ok {
197+
layout = fallback
198+
}
199+
}
200+
if envRel == "" {
201+
envRel = layout.EnvTargetPath
202+
}
201203
}
202204
if envRel == "" {
203205
items = append(items, doctorCheckItem{Name: "workspace_env_path", Message: "Could not determine quickstart env target path", Status: "warn"})
@@ -270,7 +272,7 @@ func buildWorkspaceDoctorDetails(target projectTarget) (doctorCheckCategory, map
270272
warnings = append(warnings, doctorIssue{Code: "WORKSPACE_ENV_METADATA_MISSING", Message: "Quickstart env file is missing Agora-managed project metadata comments"})
271273
}
272274

273-
appIDKey := quickstartAppIDKey(templateID)
275+
appIDKey := layout.AppIDKey
274276
if appIDKey != "" {
275277
if envAppID, ok := lookupDotenvValue(envContent, appIDKey); !ok {
276278
items = append(items, doctorCheckItem{

internal/cli/integration_project_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ func TestCLIProjectDoctorDeepDetectsWorkspaceDrift(t *testing.T) {
252252
}
253253

254254
repoRoot := t.TempDir()
255-
if err := os.MkdirAll(filepath.Join(repoRoot, "server"), 0o755); err != nil {
255+
if err := os.MkdirAll(filepath.Join(repoRoot, "server-go"), 0o755); err != nil {
256256
t.Fatal(err)
257257
}
258258
if err := writeLocalProjectBinding(repoRoot, localProjectBinding{
@@ -268,12 +268,12 @@ func TestCLIProjectDoctorDeepDetectsWorkspaceDrift(t *testing.T) {
268268
"# BEGIN AGORA CLI QUICKSTART",
269269
"# Project ID: prj_other",
270270
"# Project Name: Project Other",
271-
"AGORA_APP_ID=app_other",
272-
"AGORA_APP_CERTIFICATE=other",
271+
"APP_ID=app_other",
272+
"APP_CERTIFICATE=other",
273273
"# END AGORA CLI QUICKSTART",
274274
"",
275275
}, "\n")
276-
if err := os.WriteFile(filepath.Join(repoRoot, "server", ".env.local"), []byte(mismatched), 0o644); err != nil {
276+
if err := os.WriteFile(filepath.Join(repoRoot, "server-go", ".env"), []byte(mismatched), 0o644); err != nil {
277277
t.Fatal(err)
278278
}
279279

internal/cli/integration_quickstart_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -263,21 +263,18 @@ func TestCLIQuickstartEnvWriteUsesTargetRepoBindingPrecedence(t *testing.T) {
263263
}
264264

265265
targetDir := filepath.Join(rootDir, "demo-go")
266-
if err := os.MkdirAll(filepath.Join(targetDir, "server"), 0o755); err != nil {
266+
if err := os.MkdirAll(filepath.Join(targetDir, "server-go"), 0o755); err != nil {
267267
t.Fatal(err)
268268
}
269-
if err := os.WriteFile(filepath.Join(targetDir, "server", ".env.example"), []byte("AGORA_APP_ID=\nAGORA_APP_CERTIFICATE=\nPORT=8080\n"), 0o644); err != nil {
270-
t.Fatal(err)
271-
}
272-
if err := os.WriteFile(filepath.Join(targetDir, "server", "go.mod"), []byte("module agent-quickstart-go/server\n"), 0o644); err != nil {
269+
if err := os.WriteFile(filepath.Join(targetDir, "server-go", "env.example"), []byte("APP_ID=\nAPP_CERTIFICATE=\nPORT=8080\n"), 0o644); err != nil {
273270
t.Fatal(err)
274271
}
275272
if err := writeLocalProjectBinding(targetDir, localProjectBinding{
276273
ProjectID: alpha.ProjectID,
277274
ProjectName: alpha.Name,
278275
Region: "global",
279276
Template: "go",
280-
EnvPath: "server/.env.local",
277+
EnvPath: "server-go/.env",
281278
}); err != nil {
282279
t.Fatal(err)
283280
}
@@ -293,13 +290,16 @@ func TestCLIQuickstartEnvWriteUsesTargetRepoBindingPrecedence(t *testing.T) {
293290
if result.exitCode != 0 || !strings.Contains(result.stdout, `"projectId":"prj_alpha"`) {
294291
t.Fatalf("expected repo-local project binding precedence, got %+v", result)
295292
}
296-
envRaw, err := os.ReadFile(filepath.Join(targetDir, "server", ".env.local"))
293+
envRaw, err := os.ReadFile(filepath.Join(targetDir, "server-go", ".env"))
297294
if err != nil {
298295
t.Fatal(err)
299296
}
300-
if !strings.Contains(string(envRaw), "AGORA_APP_ID=app_alpha") || !strings.Contains(string(envRaw), "PORT=8080") || strings.Contains(string(envRaw), "AGORA_APP_ID=app_beta") {
297+
if !strings.Contains(string(envRaw), "APP_ID=app_alpha") || !strings.Contains(string(envRaw), "PORT=8080") || strings.Contains(string(envRaw), "APP_ID=app_beta") {
301298
t.Fatalf("expected target repo binding project app id in env, got %s", string(envRaw))
302299
}
300+
if _, err := os.Stat(filepath.Join(targetDir, "server", ".env.local")); !errors.Is(err, os.ErrNotExist) {
301+
t.Fatalf("did not expect a current env file in a legacy scaffold, got %v", err)
302+
}
303303
}
304304

305305
func TestCLIQuickstartEnvWriteMissingBindingEvenWhenEnvExists(t *testing.T) {

0 commit comments

Comments
 (0)