Add Go Azure Functions framework service support#8599
Conversation
📋 Milestone: June 2026This work is tracked for June 2026. The team will review it soon! |
There was a problem hiding this comment.
Pull request overview
This PR is a draft POC that adds first-class Go as a supported language for Azure Functions services in azd core, enabling azd up/deploy for Go-based Function Apps (Flex Consumption) by introducing a Go framework service, Go CLI tool wrapper, and related schema/tests.
Changes:
- Added
goas a validservices.<name>.languagevalue (schema + language parsing), plus IoC registration for the new framework service. - Implemented a Go Azure Functions framework service to restore modules, cross-compile a Linux binary, and stage a Functions deployment package.
- Updated packaging to preserve Unix file permissions in zip deploy artifacts and added unit + functional coverage for the new Go Functions sample.
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| schemas/v1.0/azure.yaml.json | Adds go to the stable schema language enum. |
| schemas/alpha/azure.yaml.json | Adds go to the alpha schema language enum. |
| cli/azd/test/functional/up_test.go | Adds an end-to-end functional test for provisioning/deploying a Go Function App sample. |
| cli/azd/test/functional/testdata/samples/gofuncapp/main.go | New “hello world” Go Functions app using the Go worker SDK. |
| cli/azd/test/functional/testdata/samples/gofuncapp/infra/resources.bicep | New Flex Consumption Function App + storage + RBAC infra for the Go sample. |
| cli/azd/test/functional/testdata/samples/gofuncapp/infra/main.parameters.json | Parameters file for the Go sample deployment. |
| cli/azd/test/functional/testdata/samples/gofuncapp/infra/main.bicep | Subscription-scope RG creation + module wiring for the Go sample. |
| cli/azd/test/functional/testdata/samples/gofuncapp/host.json | New host.json included in the Go sample. |
| cli/azd/test/functional/testdata/samples/gofuncapp/go.sum.txt | Dependencies for the Go sample (stored as .txt for embedding). |
| cli/azd/test/functional/testdata/samples/gofuncapp/go.mod.txt | Module definition for the Go sample (stored as .txt for embedding). |
| cli/azd/test/functional/testdata/samples/gofuncapp/azure.yaml | New sample project definition using host: function and language: go. |
| cli/azd/pkg/tools/golang/golang.go | New ExternalTool wrapper for the go CLI (version check, build, mod download). |
| cli/azd/pkg/rzip/rzip.go | Preserves Unix file permissions in zip entries (needed for executable Go binaries). |
| cli/azd/pkg/project/service_target_functionapp.go | Sets default remoteBuild behavior for Go Function Apps to false. |
| cli/azd/pkg/project/framework_service.go | Adds ServiceLanguageGo + alias parsing. |
| cli/azd/pkg/project/framework_service_go.go | Implements Go framework service: restore/build/package for Azure Functions deploy. |
| cli/azd/pkg/project/framework_service_go_test.go | Adds unit tests for Go framework service behavior. |
| cli/azd/cmd/container.go | Registers Go CLI singleton and Go framework service in the IoC container. |
Adds a new 'go' service language for Azure Functions, enabling `azd up` for Go-based Function Apps on Flex Consumption. This follows the pattern of existing language framework services (Python, Node, Java, .NET). Changes: - Go CLI tool wrapper (pkg/tools/golang/) with min version Go 1.24 - Framework service (pkg/project/framework_service_go.go): Restore, Build (cross-compile GOOS=linux GOARCH=amd64), Package (app binary + host.json) - IoC container registration in cmd/container.go - Schema updates for azure.yaml (v1.0 and alpha) - Function app target: Go returns false for remote build - Fix rzip to preserve Unix file permissions in zip archives - Unit tests for all framework service lifecycle methods - Functional deploy test (Test_CLI_Up_Down_GoFuncApp) with Flex Consumption infrastructure (runtime: go 1.0, managed identity, blob deploy) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
b59b004 to
c0fb25a
Compare
- Fail fast when host.json is missing instead of silently skipping - Fix duplicated 'the' typo in Bicep parameter description Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Bump min Go version to 1.22 (align with azure-functions-golang-worker) - Add ToolInPath check before running go version - Pass azd env vars to ModDownload for GOPROXY/GOPRIVATE support - Handle os.IsNotExist vs other stat errors for host.json - Use binaryPath metadata from build artifacts in Package step - Enforce remoteBuild=false for Go (error on true) - Add unit tests for Go remote build behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Restore min Go version to 1.24 (aligns with Go Functions worker needs) - Clean up temp build directory on build failure to avoid leaking dirs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use ErrorWithSuggestion for Go remoteBuild=true error - Honor full binaryPath from build metadata (not just basename) - Add unit test for rzip preserving Unix file permissions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add #nosec G107 suppression for health probe client.Do call - Document Windows limitation for binary chmod in Package step - Add Go CLI tool unit tests (CheckInstalled, Build, ModDownload) - Add parseServiceLanguage test cases for 'go' and 'golang' alias - Fix IsDotNet test to use ServiceLanguageGo instead of raw string Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix gosec G306: use os.WriteFile with 0600 then os.Chmod for execute bits - Validate relative binaryPath doesn't escape build dir with filepath.Clean Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@vhvb1989, I do think the actual SDK is pretty neat though, and I like that they followed the net/http signature of just having a body reader/writer like the stdlib http servers. Pretty cool stuff! |
- Clarify language alias comment in parseServiceLanguage - Print HTTP method in test sample function response Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JeffreyCA
left a comment
There was a problem hiding this comment.
I'm having trouble running the function after deploying from a Windows machine (Function host is not running error when accessing the endpoint):
I think it might be due to the generated .zip not having the executable permission set on the binary:
Binary must have execute permissions in the zip — fixed a pre-existing issue in rzip.go where Unix file modes were not preserved
If I instead take a packaged .zip generated from a Linux machine, then on Windows run azd deploy gofunc --from-package .\gofuncapp-gofunc-azddeploy-1781737383.zip it works:
On Windows, os.Chmod doesn't set Unix execute bits and info.Mode() returns 0666 for all files. This causes deployed binaries (e.g., Go Functions app) to lack execute permission when the zip is extracted on Linux. Fix rzip.addFile to default to 0755 on Windows, ensuring cross-platform deployments work correctly regardless of the build host OS. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
@JeffreyCA Thanks for catching the Windows issue! 🙏 The problem was in our The fix (fc2ffc5): I'll be running the ADO pipelines in live mode (no recordings) which exercises Windows, Linux, and macOS to validate the functional test works across all platforms. |
JeffreyCA
left a comment
There was a problem hiding this comment.
Thank you, works great!
hemarina
left a comment
There was a problem hiding this comment.
TL;DR: Clean POC that follows existing framework service patterns precisely. Cross-compilation, packaging, remote build rejection, and functional testing all look solid. One minor observation on the rzip change.
1. rzip.go: Blanket 0755 on all files when zipping on Windows
cli/azd/pkg/rzip/rzip.go:113-117
The fix sets header.SetMode(0755) for every file when runtime.GOOS == "windows". This is needed for Go binaries (they must be executable on Linux), but it applies to all zip-based deployments from Windows — Python, Node, .NET, Java included. Config files, JSON, etc. would also get execute permission in the zip.
This is practically harmless since Azure Functions doesn't enforce file permissions for interpreted languages. Just wanted to flag it in case precision matters down the road — one option could be letting callers pass a per-file mode callback to CreateFromDirectory, or defaulting to 0644 and using 0755 only for files that need it.
What looks good:
- Framework service follows existing patterns precisely (Python, Java, .NET)
- Cross-compilation env vars (
GOOS=linux,GOARCH=amd64,CGO_ENABLED=0) are correct binaryPathvalidation inPackage()guards against path traversal- Remote build rejection with helpful error message and suggestion
golangalias forgolanguage kind is a nice UX touch- Comprehensive unit tests covering restore, build, package, missing host.json, and no build output
- Functional test with retry logic for cold-start timing
… binary - rzip: replace blanket Windows 0755 with opt-in WithExecutableMatcher so only flagged entries (the Go worker binary) get +x; keeps the shared utility generic - project: pass executable matcher only for Go function deploys - framework_service_go: trust Build-step binaryPath metadata directly (we own the build), removing fragile path-traversal validation; link Go worker spec for the hardcoded binary name and linux/amd64 target - schemas: add 'golang' alias alongside 'go' to match py/python precedent - tests: add unknown-language IsDotNet case and rzip executable-matcher test Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
POC: Go Azure Functions Support for azd core
Closes #8307
What this adds
A new
goservice language for Azure Functions, enablingazd upfor Go-based Function Apps on Flex Consumption. This follows the pattern of existing language framework services (Python, Node, Java, .NET).Components
pkg/tools/golang/golang.goExternalToolinterface —CheckInstalled()with min version Go 1.24,Build(),ModDownload()pkg/project/framework_service_go.goFrameworkService— Restore (go mod download), Build (cross-compileGOOS=linux GOARCH=amd64 CGO_ENABLED=0), Package (binary + host.json)cmd/container.goschemas/v1.0/azure.yaml.json,schemas/alpha/azure.yaml.jsongoto language enumpkg/project/service_target_functionapp.gofalsefor remote buildpkg/rzip/rzip.gopkg/project/framework_service_go_test.gotest/functional/up_test.goTest_CLI_Up_Down_GoFuncApp— provision → deploy → health probe → cleanuptest/functional/testdata/samples/gofuncapp/Deployment model
functionAppConfig.runtime: { name: 'go', version: '1.0' }worker.config.json— deployment package is justapp+host.jsonAzureWebJobsStorage__accountName)SystemAssignedIdentityKey learnings from prototyping
azure-functions-golang-workerSDKgo(notcustom) on Flex ConsumptionFUNCTIONS_WORKER_RUNTIMEapp setting is not needed (and is rejected by Flex Consumption)rzip.gowhere Unix file modes were not preservedTODO before merging