What's broken
Every bridge.groovy subcommand fails at runtime with groovy.lang.MissingPropertyException: No such property: TRACKER_URL for class: bridge. The bridge's configuration variables (TRACKER_URL, API_TOKEN, AUTH_SCHEME, ENV) are declared as top-level def locals, so the cmd_* methods and the httpGet/httpPost helpers cannot see them.
Which layer
tools/jira/bridge.groovy lines 40–44:
def ENV = System.getenv()
def TRACKER_URL = ENV['ISSUE_TRACKER_URL'] ?: ''
def PROJECT_KEY = ENV['ISSUE_TRACKER_PROJECT'] ?: ''
def API_TOKEN = ENV['JIRA_API_TOKEN'] ?: ''
def AUTH_SCHEME = ENV['JIRA_AUTH_SCHEME'] ?: 'Basic'
How to reproduce
ISSUE_TRACKER_URL=https://issues.apache.org/jira \
groovy tools/jira/bridge.groovy search 'project = FOO'
Result:
Caught: groovy.lang.MissingPropertyException: No such property: TRACKER_URL for class: bridge
at bridge.cmd_search(bridge.groovy:182)
at bridge.run(bridge.groovy:372)
The same failure hits every read and write subcommand. It also surfaces in CI: tools/jira/tests/test_bridge_write.py fails (prek run --all-files), because the test harness shells out to the real bridge.
Expected vs actual
- Expected: the bridge resolves its configuration from the environment and runs the requested subcommand.
- Actual: it throws
MissingPropertyException before any HTTP call.
Root cause: in a Groovy script, a bare top-level def x = … is a local variable of the generated run() method, not an entry in the script binding — so it is invisible inside methods compiled onto the script class. TRACKER_URL is merely the first such variable referenced (when building the request URL); API_TOKEN and AUTH_SCHEME fail the same way once that one is fixed. The top-level if (!TRACKER_URL) guard passes because it runs inside run(), which masks the problem until a cmd_* method is entered.
Fix: annotate the script-level config variables with @groovy.transform.Field (via import groovy.transform.Field) so they become fields visible to every method.
Surface area (optional)
PROJECT_KEY is affected by the same scoping issue but is currently dead code (defined, never read), so it has no runtime impact today — promoting it to @Field alongside the others keeps things consistent.
- The other Groovy tool,
tools/dashboard-generator/reference.groovy, is not affected: it defines no methods (linear script + closures, which do capture the script scope) and reads no environment variables.
What's broken
Every
bridge.groovysubcommand fails at runtime withgroovy.lang.MissingPropertyException: No such property: TRACKER_URL for class: bridge. The bridge's configuration variables (TRACKER_URL,API_TOKEN,AUTH_SCHEME,ENV) are declared as top-leveldeflocals, so thecmd_*methods and thehttpGet/httpPosthelpers cannot see them.Which layer
tools/jira/bridge.groovylines 40–44:How to reproduce
ISSUE_TRACKER_URL=https://issues.apache.org/jira \ groovy tools/jira/bridge.groovy search 'project = FOO'Result:
The same failure hits every read and write subcommand. It also surfaces in CI:
tools/jira/tests/test_bridge_write.pyfails (prek run --all-files), because the test harness shells out to the real bridge.Expected vs actual
MissingPropertyExceptionbefore any HTTP call.Root cause: in a Groovy script, a bare top-level
def x = …is a local variable of the generatedrun()method, not an entry in the script binding — so it is invisible inside methods compiled onto the script class.TRACKER_URLis merely the first such variable referenced (when building the request URL);API_TOKENandAUTH_SCHEMEfail the same way once that one is fixed. The top-levelif (!TRACKER_URL)guard passes because it runs insiderun(), which masks the problem until acmd_*method is entered.Fix: annotate the script-level config variables with
@groovy.transform.Field(viaimport groovy.transform.Field) so they become fields visible to every method.Surface area (optional)
PROJECT_KEYis affected by the same scoping issue but is currently dead code (defined, never read), so it has no runtime impact today — promoting it to@Fieldalongside the others keeps things consistent.tools/dashboard-generator/reference.groovy, is not affected: it defines no methods (linear script + closures, which do capture the script scope) and reads no environment variables.