Skip to content

Commit 7091841

Browse files
authored
Merge pull request #70 from stackql/feature/ja-updates
v1.9.1
2 parents 4aa34e1 + 5298817 commit 7091841

File tree

15 files changed

+220
-15
lines changed

15 files changed

+220
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
# Changelog
22

3-
## 1.8.8 (2025-10-15)
3+
## 1.9.1 (2025-10-15)
44

5+
- added `--output-file` argument
56
- Added performance enhancement query strategy
6-
7-
## 1.8.7 (2025-10-14)
8-
97
- Added tab completion
108
- Added enhanced logging decorators
119

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"stack_name": "stackql-serverless",
3+
"stack_env": "prd",
4+
"databricks_workspace_name": "stackql-serverless-prd-workspace",
5+
"databricks_workspace_id": "4014389171618363",
6+
"databricks_deployment_name": "dbc-5a3a87f7-6914",
7+
"databricks_workspace_status": "RUNNING",
8+
"databricks_workspace_url": "https://dbc-5a3a87f7-6914.cloud.databricks.com"
9+
}

examples/databricks/serverless/resources/databricks_account/workspace.iql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ SELECT
2525
SELECT
2626
'{{ workspace_name }}' AS databricks_workspace_name,
2727
workspace_id AS databricks_workspace_id,
28-
deployment_name AS databricks_deployment_name
28+
deployment_name AS databricks_deployment_name,
29+
workspace_status AS databricks_workspace_status,
30+
'https://' || deployment_name || '.cloud.databricks.com' AS databricks_workspace_url
2931
FROM databricks_account.provisioning.workspaces
3032
WHERE account_id = '{{ databricks_account_id }}'
3133
AND workspace_name = '{{ workspace_name }}'

examples/databricks/serverless/stackql_manifest.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,9 @@ resources:
381381
exports:
382382
- databricks_workspace_name
383383
- databricks_workspace_id
384-
- databricks_deployment_name
384+
- databricks_deployment_name
385+
- databricks_workspace_status
386+
- databricks_workspace_url
385387

386388
- name: databricks_account/workspace_group
387389
props:
@@ -489,4 +491,9 @@ resources:
489491
securable_type = 'external_location' AND
490492
deployment_name = '{{ databricks_deployment_name }}';
491493
492-
494+
exports:
495+
- databricks_workspace_name
496+
- databricks_workspace_id
497+
- databricks_deployment_name
498+
- databricks_workspace_status
499+
- databricks_workspace_url

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
setup(
1212
name='stackql-deploy',
13-
version='1.8.8',
13+
version='1.9.1',
1414
description='Model driven resource provisioning and deployment framework using StackQL.',
1515
long_description=readme,
1616
long_description_content_type='text/x-rst',

stackql_deploy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.8.8'
1+
__version__ = '1.9.1'

stackql_deploy/cli.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,12 @@ def setup_command_context(
162162
@click.argument('stack_env')
163163
@add_common_options
164164
@add_stackql_kwarg_options
165+
@click.option('--output-file', default=None,
166+
help='File path to write deployment outputs as JSON.')
165167
@click.pass_context
166168
def build(ctx, stack_dir, stack_env, log_level, env_file,
167169
env, dry_run, show_queries, on_failure,
168-
custom_registry, download_dir ):
170+
custom_registry, download_dir, output_file):
169171
"""Create or update resources."""
170172

171173
from .cmd.build import StackQLProvisioner
@@ -184,7 +186,7 @@ def build(ctx, stack_dir, stack_env, log_level, env_file,
184186
f"to environment: [{stack_env}]")
185187
print_unicode_box(message, BorderColor.YELLOW)
186188

187-
provisioner.run(dry_run, show_queries, on_failure)
189+
provisioner.run(dry_run, show_queries, on_failure, output_file)
188190
click.echo("🎯 dry-run build complete" if dry_run
189191
else "🚀 build complete")
190192

@@ -232,9 +234,11 @@ def teardown(ctx, stack_dir, stack_env, log_level, env_file,
232234
@click.argument('stack_env')
233235
@add_common_options
234236
@add_stackql_kwarg_options
237+
@click.option('--output-file', default=None,
238+
help='File path to write deployment outputs as JSON.')
235239
@click.pass_context
236240
def test(ctx, stack_dir, stack_env, log_level, env_file,
237-
env, dry_run, show_queries, on_failure, custom_registry, download_dir):
241+
env, dry_run, show_queries, on_failure, custom_registry, download_dir, output_file):
238242
"""Run test queries for the stack."""
239243

240244
from .cmd.test import StackQLTestRunner
@@ -253,7 +257,7 @@ def test(ctx, stack_dir, stack_env, log_level, env_file,
253257
f"in environment: [{stack_env}]")
254258
print_unicode_box(message, BorderColor.YELLOW)
255259

256-
test_runner.run(dry_run, show_queries, on_failure)
260+
test_runner.run(dry_run, show_queries, on_failure, output_file)
257261
click.echo(f"🔍 tests complete (dry run: {dry_run})")
258262

259263
#

stackql_deploy/cmd/base.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# cmd/base.py
2+
import os
3+
import json
24
from ..lib.utils import (
35
perform_retries,
46
run_stackql_command,
@@ -468,3 +470,67 @@ def run_command(self, command_query, command_retries, command_retry_delay, dry_r
468470
)
469471
else:
470472
self.logger.info("command query not configured, skipping command...")
473+
474+
def process_stack_exports(self, dry_run, output_file=None):
475+
"""
476+
Process root-level exports from manifest and write to JSON file
477+
"""
478+
if not output_file:
479+
return
480+
481+
self.logger.info("📦 processing stack exports...")
482+
483+
manifest_exports = self.manifest.get('exports', [])
484+
485+
if dry_run:
486+
total_vars = len(manifest_exports) + 2 # +2 for stack_name and stack_env
487+
self.logger.info(
488+
f"📁 dry run: would export {total_vars} variables to {output_file} "
489+
f"(including automatic stack_name and stack_env)"
490+
)
491+
return
492+
493+
# Collect data from global context
494+
export_data = {}
495+
missing_vars = []
496+
497+
# Always include stack_name and stack_env automatically
498+
export_data['stack_name'] = self.stack_name
499+
export_data['stack_env'] = self.stack_env
500+
501+
for var_name in manifest_exports:
502+
# Skip stack_name and stack_env if they're explicitly listed (already added above)
503+
if var_name in ('stack_name', 'stack_env'):
504+
continue
505+
506+
if var_name in self.global_context:
507+
value = self.global_context[var_name]
508+
# Parse JSON strings back to their original type if they were serialized
509+
try:
510+
if isinstance(value, str) and (value.startswith('[') or value.startswith('{')):
511+
value = json.loads(value)
512+
except (json.JSONDecodeError, ValueError):
513+
# Keep as string if not valid JSON
514+
pass
515+
export_data[var_name] = value
516+
else:
517+
missing_vars.append(var_name)
518+
519+
if missing_vars:
520+
catch_error_and_exit(
521+
f"exports failed: variables not found in context: {missing_vars}",
522+
self.logger
523+
)
524+
525+
# Ensure destination directory exists
526+
dest_dir = os.path.dirname(output_file)
527+
if dest_dir and not os.path.exists(dest_dir):
528+
os.makedirs(dest_dir, exist_ok=True)
529+
530+
# Write JSON file
531+
try:
532+
with open(output_file, 'w') as f:
533+
json.dump(export_data, f, indent=2)
534+
self.logger.info(f"✅ exported {len(export_data)} variables to {output_file}")
535+
except Exception as e:
536+
catch_error_and_exit(f"failed to write exports file {output_file}: {e}", self.logger)

stackql_deploy/cmd/build.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def process_script_resource(self, resource, dry_run, full_context):
3535
except Exception as e:
3636
catch_error_and_exit(f"script failed: {e}", self.logger)
3737

38-
def run(self, dry_run, show_queries, on_failure):
38+
def run(self, dry_run, show_queries, on_failure, output_file=None):
3939

4040
start_time = datetime.datetime.now()
4141

@@ -409,5 +409,8 @@ def run(self, dry_run, show_queries, on_failure):
409409
elif type == 'query':
410410
self.logger.info(f"✅ successfully exported variables for query in {resource['name']}")
411411

412+
# Process stack-level exports after all resources are deployed
413+
self.process_stack_exports(dry_run, output_file)
414+
412415
elapsed_time = datetime.datetime.now() - start_time
413416
self.logger.info(f"deployment completed in {elapsed_time}")

stackql_deploy/cmd/test.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from .base import StackQLBase
1212

1313
class StackQLTestRunner(StackQLBase):
14-
def run(self, dry_run, show_queries, on_failure):
14+
def run(self, dry_run, show_queries, on_failure, output_file=None):
1515

1616
start_time = datetime.datetime.now()
1717

@@ -146,3 +146,7 @@ def run(self, dry_run, show_queries, on_failure):
146146

147147
elapsed_time = datetime.datetime.now() - start_time
148148
self.logger.info(f"deployment completed in {elapsed_time}")
149+
150+
# Process stack-level exports if specified
151+
if output_file:
152+
self.process_stack_exports(dry_run, output_file)

0 commit comments

Comments
 (0)