Skip to content

Make appId optional in flow config#3086

Open
noomorph wants to merge 1 commit intomobile-dev-inc:mainfrom
noomorph:optional-appid-config
Open

Make appId optional in flow config#3086
noomorph wants to merge 1 commit intomobile-dev-inc:mainfrom
noomorph:optional-appid-config

Conversation

@noomorph
Copy link
Copy Markdown

@noomorph noomorph commented Mar 25, 2026

Fixes #1692

Proposed changes

Allow running Maestro flows without specifying appId (or url) in the YAML config section.

Currently every flow must declare appId or url in its frontmatter, even if the flow only opens a deep link or interacts with whatever app is already on screen. This change moves the validation from config-level to command-level: a flow without appId parses fine, but commands that need one (launchApp, stopApp, killApp, clearState, setPermissions) will throw an error if no appId is available — either inline or from config.

Before — always required, even for flows that don't need it:

appId: com.example.app  # mandatory
---
- openLink: https://example.com

After — optional, commands that need it say so:

name: My deep-link flow
---
- openLink: https://example.com

And if you do need launchApp, provide it inline:

name: Multi-app flow
---
- launchApp: com.app.one
- tapOn: "Login"
- launchApp: com.app.two

Error when appId is missing and a command needs it:

No appId specified for 'launchApp'. Provide it as a parameter or in the flow config:
appId: com.example.app
---
- launchApp

What changed

  • YamlConfigappId is now nullable, removed the ConfigParseError("missing_app_target") check
  • YamlFluentCommand — all appId: String params become String?, added requireAppId() helper for per-command validation
  • MaestroFlowParser — removed dead ConfigParseError handler, added SyntaxError case to ToCommandsException handler for clean error messages
  • Removed ConfigParseError class (no longer thrown)

No changes to Commands.kt models, Maestro.kt, Driver.kt, or Orchestra.kt.

Testing

  • Unit tests: flow without appId + openLink (parses), flow without appId + inline launchApp (parses), flow without appId + bare launchApp (errors)
  • Integration test: full flow execution without config appId using inline launchApp
  • Updated e018_config_missing_appId workspace error test to verify the new per-command error message
  • All existing tests pass (./gradlew :maestro-orchestra:test :maestro-test:test)

Copy link
Copy Markdown
Contributor

@Fishbowler Fishbowler left a comment

Choose a reason for hiding this comment

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

With appIds and URLs required by a number of commands and by Maestro Cloud, and a natural configuration for many environments, I'm not sure that I understand the value of this change well enough to justify the complexity it introduces.

@noomorph
Copy link
Copy Markdown
Author

noomorph commented Mar 25, 2026

@Fishbowler two cases where this matters:

Subflows that don't launch or stop anything — a login helper, a checkout flow, anything that just interacts with what's on screen:

name: Log in as a temporary user
---
- runScript: createTemporaryAccountViaTestService.js
- tapOn: Email
- inputText: ${output.email}
- tapOn: Password
- inputText: ${output.password}
- tapOn: Sign In

Today this needs a dummy appId even though no command uses it. And from what I can tell, subflow config appId is ignored at runtime anyway — the parent's config is used for command execution. So we're requiring a field that gets silently discarded — feels more like an abstraction leak than a feature.

You could put a dummy appId there, sure, but normally, if multiple apps share the same screen (login, onboarding) and you want one subflow for it — whose appId do you put? 🤔

Then there's #1692 — flows that don't target an app at all (deep link testing, web content). There's no appId to provide, not even via env var.

name: Flow without appId
---
- openLink: https://example.com
- tapOn: Learn more

Regarding Maestro Cloud — good point, I hadn't considered that. Does Cloud need appId on subflows too, or only on entry point flows?

That said, I might be missing the full picture — I noticed appId is used implicitly in some places (e.g. Android settling), and I don't have visibility into what Cloud expects. If this creates more problems than it solves, happy to address concerns or close it if you feel like this absolutely goes against your direction.

@Fishbowler
Copy link
Copy Markdown
Contributor

Cloud, like Studio, is just a wrapper around Maestro. There's a check on upload that the appId of the top level flows matches the uploaded binary.

The usecase in #1692 alone isn't enough to justify this change.
I agree that subflows have an often pointless appId.

That being said, there's now zero mandatory fields. Does your change allow for the first YAML document in a file to be empty?

@noomorph
Copy link
Copy Markdown
Author

noomorph commented Mar 25, 2026

Cloud, like Studio, is just a wrapper around Maestro. There's a check on upload that the appId of the top level flows matches the uploaded binary.

So if I understand correctly, I’d basically need to enforce validation that top-level flows must include appId: ..., right? 🤔

That being said, there's now zero mandatory fields. Does your change allow for the first YAML document in a file to be empty?

@Fishbowler, would it be reasonable to handle it that way? As things stand, I believe there’s still some validation left (something like "when parsed, it must not be an array"). I was also wondering whether removing it would be acceptable. To me, removing it seems reasonable. 🙂

@Fishbowler
Copy link
Copy Markdown
Contributor

I’d basically need to enforce validation that top-level flows must include appId: ..., right?

Correct.

That being said, there's now zero mandatory fields. Does your change allow for the first YAML document in a file to be empty?

@Fishbowler, would it be reasonable to handle it that way?

I think an empty first document is acceptable. I think no first document probably isn't.
Have a check of what you've currently got, and see if it works with an empty document at the top of a subflow?

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.

Allow for running Maestro flows that don't have appId in frontmatter

2 participants