Skip to content

Add azure.logicappsstandard extension#8005

Open
ronaldbosma wants to merge 38 commits intoAzure:mainfrom
ronaldbosma:add-logicappsstandard-extension
Open

Add azure.logicappsstandard extension#8005
ronaldbosma wants to merge 38 commits intoAzure:mainfrom
ronaldbosma:add-logicappsstandard-extension

Conversation

@ronaldbosma
Copy link
Copy Markdown
Contributor

@ronaldbosma ronaldbosma commented May 1, 2026

Add azure.logicappsstandard extension that makes it possible to package Logic Apps Standard projects. It includes support for custom code projects. It uses the host specific exclusion file (e.g. .funcignore) to exclude files and folders from the package.

Fixes #812. Discussed in #6956.

Design decisions

  • There's no validation that checks if the folder containing the Logic App Standard project contains certain files, because there are no specific required files. Even deploying an empty .zip file to a Logic App succeeds.
  • Only accept function as host in combination with language: logicappsstandard because Logic App Standard uses the Azure Function Runtime under the hood. This prevents the extension from silently proceeding through packaging when another host is configured and likely failing with a confusing error at deploy time.

Usage

Sample usage in azure.yaml for Logic App project without custom code project where the ./src/logicapp folder contains the Logic App assets like the host.json and workflows:

services:
  logicapp:
    project: ./src/logicapp
    host: function
    language: logicappsstandard

Sample usage in azure.yaml for Logic App project with custom code project (./src/logicapp/Functions/Functions.csproj), where the ./src/logicApp/Workflows folder contains the Logic App assets like the host.json and workflows:

services:
  logicapp:
    project: ./src/logicapp
    dist: Workflows
    host: function
    language: logicappsstandard
    customCodeProject: Functions/Functions.csproj

@ronaldbosma
Copy link
Copy Markdown
Contributor Author

ronaldbosma commented May 1, 2026

Note that I don't have any prior experience with Go and with creating azd extensions. I've used the docs under https://github.com/Azure/azure-dev/tree/main/cli/azd/docs/extensions, existing extensions under https://github.com/Azure/azure-dev/tree/main/cli/azd/extensions and Copilot to create this extension.

Let me know if anything needs to change.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new first-party azure.logicappsstandard azd extension that implements a framework service provider for packaging Logic Apps Standard projects (optionally building a configured custom code .csproj), along with CI/release pipeline wiring.

Changes:

  • Introduces a new Go-based extension (azure.logicappsstandard) that registers logicappsstandard as a framework-service-provider language and packages the service as a directory artifact.
  • Adds unit tests for customCodeProject detection, path validation, dotnet invocation, and packaging path selection.
  • Adds GitHub Actions lint workflow and Azure DevOps release pipeline definition for the new extension.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
eng/pipelines/release-ext-azure-logicappsstandard.yml Adds ADO release pipeline entry for the new extension.
.github/workflows/lint-ext-azure-logicappsstandard.yml Adds extension-scoped Go lint workflow trigger.
cli/azd/extensions/azure.logicappsstandard/main.go Extension entrypoint wiring azdext.Run(...).
cli/azd/extensions/azure.logicappsstandard/internal/cmd/root.go Root command defining listen/metadata/version commands.
cli/azd/extensions/azure.logicappsstandard/internal/cmd/listen.go Registers the framework service provider for logicappsstandard.
cli/azd/extensions/azure.logicappsstandard/internal/project/framework_service_logicappsstandard.go Implements packaging + optional dotnet restore/build for custom code projects.
cli/azd/extensions/azure.logicappsstandard/internal/project/framework_service_logicappsstandard_test.go Unit tests for provider behavior and dotnet invocation.
cli/azd/extensions/azure.logicappsstandard/extension.yaml Declares extension metadata and capabilities.
cli/azd/extensions/azure.logicappsstandard/version.txt Initial extension version.
cli/azd/extensions/azure.logicappsstandard/go.mod New module definition and dependencies.
cli/azd/extensions/azure.logicappsstandard/go.sum Dependency lockfile for the new module.
cli/azd/extensions/azure.logicappsstandard/build.sh Local build script for cross-compiling extension binaries.
cli/azd/extensions/azure.logicappsstandard/build.ps1 PowerShell variant of the local build script.
cli/azd/extensions/azure.logicappsstandard/README.md Usage + local development docs for the extension.
cli/azd/extensions/azure.logicappsstandard/CHANGELOG.md Initial changelog entry.

Comment thread cli/azd/extensions/azure.logicappsstandard/build.sh
Comment thread eng/pipelines/release-ext-azure-logicappsstandard.yml
Comment thread cli/azd/extensions/azure.logicappsstandard/main.go Outdated
Comment thread cli/azd/extensions/azure.logicappsstandard/internal/cmd/root.go
Comment thread .github/workflows/lint-ext-azure-logicappsstandard.yml
Comment thread cli/azd/extensions/azure.logicappsstandard/go.mod Outdated
Comment thread cli/azd/extensions/azure.logicappsstandard/CHANGELOG.md Outdated
@ronaldbosma ronaldbosma requested a review from Copilot May 1, 2026 18:36
…kServiceProvider functions

Co-authored-by: Copilot <copilot@github.com>
Copy link
Copy Markdown
Member

@jongio jongio left a comment

Choose a reason for hiding this comment

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

All my prior findings are addressed - version.go, build script paths, CI scripts, and .golangci.yaml are all in place. The path traversal protection (resolvePathWithinBase) and nil checks are solid additions.

One remaining issue: the module rename from azure.logicappsstandard to azurelogicappsstandard (commit 4c99fcb) created a mismatch in the ldflags paths. See inline comment.

Comment thread cli/azd/extensions/azure.logicappsstandard/build.sh Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 19 out of 20 changed files in this pull request and generated 3 comments.

Comment thread cli/azd/extensions/azure.logicappsstandard/ci-build.ps1 Outdated
Comment thread cli/azd/extensions/azure.logicappsstandard/build.ps1 Outdated
Copy link
Copy Markdown
Member

@jongio jongio left a comment

Choose a reason for hiding this comment

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

Build script ldflags paths now correctly target azurelogicappsstandard/internal/version, matching the Go module name. All my prior findings across both reviews are addressed. No new issues.

@jongio
Copy link
Copy Markdown
Member

jongio commented May 1, 2026

@wbreza all the feedback from both of us has been addressed. Can you take another look?

Copilot AI added a commit that referenced this pull request May 1, 2026
Agent-Logs-Url: https://github.com/Azure/azure-dev/sessions/d45947bc-4f2d-4c36-a8cf-443bfa9df22b

Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
@jongio
Copy link
Copy Markdown
Member

jongio commented May 1, 2026

The customCodeProject property name follows the existing camelCase convention for azure.yaml schema properties (remoteBuild, resourceGroup, apiVersion, etc.) - that's correct.

However, the README examples use logicApp and src/logicApp for the service name and project directory. Every other azure.yaml example in the repo uses lowercase for service names and directories: web, api, func, app, job, src/web, src/api, src/dotnet, etc.

Consider changing the examples to lowercase for consistency:

services:
  logic-app:
    project: ./src/logic-app
    host: function
    language: logicappsstandard

@wbreza - can you confirm the convention here? Should service names in documentation examples stay lowercase/kebab-case?

@ronaldbosma
Copy link
Copy Markdown
Contributor Author

The customCodeProject property name follows the existing camelCase convention for azure.yaml schema properties (remoteBuild, resourceGroup, apiVersion, etc.) - that's correct.

However, the README examples use logicApp and src/logicApp for the service name and project directory. Every other azure.yaml example in the repo uses lowercase for service names and directories: web, api, func, app, job, src/web, src/api, src/dotnet, etc.

Consider changing the examples to lowercase for consistency:

services:
  logic-app:
    project: ./src/logic-app
    host: function
    language: logicappsstandard

@wbreza - can you confirm the convention here? Should service names in documentation examples stay lowercase/kebab-case?

@jongio I've updated the readme to use lowercase in the snippets. I couldn't find a good service related sample in the documentation because they're all one word. But under https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/layered-provisioning#example-monorepo-with-multiple-services the layers use lowercase as the convention. So, I went with that.

Copy link
Copy Markdown
Member

@jongio jongio left a comment

Choose a reason for hiding this comment

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

Addresses my naming convention feedback. README examples now use lowercase logicapp for service names and directories, matching the repo's convention. All findings from my previous reviews are addressed. No new issues.

@jongio
Copy link
Copy Markdown
Member

jongio commented May 4, 2026

@wbreza - all review findings have been addressed across 4 review cycles (version injection, build script paths, CI scripts, and naming conventions). This looks ready for your final approval.

Copy link
Copy Markdown
Member

@jongio jongio left a comment

Choose a reason for hiding this comment

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

No new issues. The cspell addition is consistent with the lowercase naming convention fix.

@wbreza
Copy link
Copy Markdown
Contributor

wbreza commented May 4, 2026

Great work @ronaldbosma — the extension is looking solid after 4 review cycles. A few items:

✅ Naming confirmation: logicappsstandard is the right name. Standard and Consumption are architecturally different products with incompatible deployment models, so the explicit suffix prevents user confusion and future-proofs the namespace. Good call.

✅ Convention confirmation (re: @jongio's earlier question): Lowercase/kebab-case for service names in docs is correct. The updates look good.

🟡 One change needed before approval — host validation:

This is the first language extension tightly coupled to a specific host type (function). Today, if a user misconfigures their azure.yaml with host: appservice + language: logicappsstandard, the extension would silently proceed through packaging and likely fail with a confusing error at deploy time.

I'd like to see a lifecycle event handler registered in listen.go that validates the host early in the pipeline. Something like:

func configureListen(host *azdext.ExtensionHost) {
    host.WithFrameworkService("logicappsstandard", func() azdext.FrameworkServiceProvider {
        return project.NewLogicAppsStandardFrameworkServiceProvider()
    })

    // Validate host compatibility early — Logic Apps Standard requires the function host
    host.WithServiceEventHandler(
        "prepackage",
        func(ctx context.Context, event *azdext.ServiceEvent) error {
            if event.ServiceConfig.Host != "function" {
                return fmt.Errorf(
                    "Logic Apps Standard requires 'host: function' in azure.yaml, "+
                    "but found 'host: %s'. Update your service configuration",
                    event.ServiceConfig.Host,
                )
            }
            return nil
        },
        &azdext.ServiceEventOptions{Language: "logicappsstandard"},
    )
}

This catches the misconfiguration immediately with a clear, actionable error instead of letting users get deep into the pipeline before failing. Since this is the first extension with a host constraint, it also sets a good pattern for future extensions.

Everything else looks good to go — the packaging logic, path validation, and framework integration are well-implemented. Once the host validation is added, this is ready for approval. 🚀

… from azure.logicappsstandard extension

Co-authored-by: Copilot <copilot@github.com>
@ronaldbosma
Copy link
Copy Markdown
Contributor Author

ronaldbosma commented May 5, 2026

Hi @wbreza.

I've made host: function mandatory when using language: logicappsstandard. I updated the initialize method in the framework service provider, which gives an immediate error when trying to package. The initialize method already has other validation logic to check if the custom code project file exists, so placing the validation here is more inline with the rest of the extension's implementation.


I tried this snippet per your suggesting (with a little tweak because azdext.ServiceEvent should be azdext.ServiceEventArgs, which has a Service property):

// Validate host compatibility early — Logic Apps Standard requires the function host
host.WithServiceEventHandler(
	"prepackage",
	func(ctx context.Context, args *azdext.ServiceEventArgs) error {
		if args.Service.Host != "function" {
			return fmt.Errorf(
				"Logic Apps Standard requires 'host: function' in azure.yaml, "+
					"but found 'host: %s'. Update your service configuration",
				args.Service.Host,
			)
		}
		return nil
	},
	&azdext.ServiceEventOptions{Language: "logicappsstandard"},
)

The extension builds successfully but I got the error ERROR: initializing service 'logicapp', rpc error: code = Unavailable desc = transport is closing when running azd package on a sample. Even with host: function.

I also tried this simplified version:

host.WithServiceEventHandler("prepackage", func(ctx context.Context, args *azdext.ServiceEventArgs) error {
	return nil
}, nil)

But that resulted in this error during packaging: ERROR: initializing service 'logicapp', channel closed by broker

Let me know if using the initialize method is not OK and I'll give it another go.

Copy link
Copy Markdown
Member

@jongio jongio left a comment

Choose a reason for hiding this comment

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

Host validation looks good. Placing it in Initialize() is the right call - it's consistent with the existing validation pattern in that method and gives a clear, early error. The test coverage is solid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

customer-reported identify a customer issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for Logic Apps

4 participants