Skip to content

Commit 3b30189

Browse files
drernieclaude
andauthored
Release v0.11.1 - Custom Athena workgroup for standalone deployments (#321)
* feat: conditionally resolve athena workgroup * docs(spec): comprehensive setup wizard redesign proposal Add three specification documents analyzing and proposing setup wizard improvements: 1. 03-current-wizard.md - Executive analysis of current 7-phase wizard - Documents two critical human decisions - Identifies workgroup discovery issues (legacy vs new stacks) - Outlines architectural constraints for conditional resource creation 2. 04-setup-pitch.md - High-level refactoring strategy - Proposes consolidation from 7 phases to 4 phases - Fold deployment directly into setup (no separate deploy command) - Single command completes entire workflow with progress visibility - Three auto-detected paths: enabled/disabled/legacy 3. 05-complete-user-flows.md - Comprehensive user journey design - Context-first approach: show state before asking questions - Minimal but complete decision trees for all scenarios - Escape hatches: disable integration, switch modes, review-only - Golden paths optimized (hit enter for recommended actions) - Covers: first-time setup, updates, mode switching, enable/disable Key insight: Wizard is the only interface - must support all lifecycle operations (configure, enable, disable, switch modes, update) with clear context and minimal questions. Related to workgroup resolution strategy (spec/a09-managed-workgroup/01-02) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * feat(setup): implement unified setup flow * feat(setup): improve integrated flow UX 1. Add "Disable integration?" as first prompt when integration is running - Previously buried after "Update credentials?" and "Review config?" - Users now have immediate access to disable without declining prompts 2. Show status with webhook URL after setup completes - Displays after: update-integration-secret, enable-integration, review-only - Uses default timer (auto-refreshes during updates, exits when stable) - Gives users immediate confirmation of webhook URL and stack state 3. Simplify status display output - Remove redundant "Benchling URL" (duplicate of "Webhook URL") - Compact labels: "Catalog DNS" → "Catalog", "Stack Status" → "Status" - Inline region with stack name: "Stack: quilt-staging (us-east-1)" - Shorten secret display: "BenchlingSecret" instead of full ARN suffix - Compact time format: "1 day ago" → "1d ago" - Single-line workgroup instead of nested structure - Remove CloudWatch Logs section (available via 'npm run logs') Result: Information-dense but scannable status display with critical info (webhook URL, status, secret freshness) visible at a glance. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(status): wait for ECS rollout completion before exiting The status command would prematurely exit when CloudFormation reached a terminal state (e.g., UPDATE_COMPLETE), even though ECS services were still rolling out new tasks. This caused confusing "deployment complete" messages when tasks were still pending or deployments were IN_PROGRESS. Changes: - Enhanced isTerminalStatus() to check both CloudFormation stack status and ECS service rollout states - Deployment now only exits when: * CloudFormation stack is in terminal state (COMPLETE/FAILED) * All ECS services have rolloutState: COMPLETED (not IN_PROGRESS) * No ECS services have pending tasks - Updated tests to verify behavior and reduce brittleness by testing return values instead of console output strings Also includes integrated mode deployment tracking cleanup from previous work (clearDeployments() calls in setup-wizard.ts). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(setup): clear deployment tracking when configuring integrated mode **Problem:** The `status` and `logs` commands showed inconsistent webhook URLs after switching from standalone to integrated mode: - `status`: Read from CloudFormation (correct) - `logs`: Read from stale deployment tracking (incorrect) **Root Cause:** When switching from standalone to integrated mode, the setup wizard never cleared the old deployment tracking data, leaving stale standalone webhook URLs in `~/.config/benchling-webhook/{profile}/deployments.json`. **Solution:** Clear all active deployments when configuring integrated mode in the setup wizard. This ensures that: 1. Stale standalone URLs are removed 2. The `logs` command queries CloudFormation for the correct URL 3. The cached URL matches the actual integrated stack endpoint **Changes:** - `bin/commands/setup-wizard.ts`: Clear active deployments in all integrated mode actions: - `update-integration-secret` - `enable-integration` - `disable-integration` - `review-only` (when integrated) **Testing:** ```bash # Before: logs showed stale standalone URL npm run setup -- logs --profile default # Webhook: https://dchv0dj8u4.execute-api.us-east-1.amazonaws.com/prod (wrong) # Run setup to trigger cleanup npm run setup -- --profile default --yes # After: both commands show correct integrated URL npm run setup -- status --profile default --timer 0 npm run setup -- logs --profile default # Webhook: https://d9hjzu4vka.execute-api.us-east-1.amazonaws.com/benchling (correct) ``` Fixes inconsistent webhook URL display between status and logs commands. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(wizard): remove duplicate disable confirmation and clarify impact - Remove redundant "Stop webhook?" prompt in setup-wizard (user already confirmed in Phase 5) - Update Phase 5 prompt to clearly state webhook resources will be destroyed - Clarify that wizard must be re-run to recreate (not just "re-enable") 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(wizard): remove duplicate standalone deployment prompt When integration is disabled, automatically proceed to standalone deployment instead of asking a redundant confirmation question. Now explicitly states "Switching to standalone deployment..." for clarity. Also improves status command to show Athena workgroup for both standalone and integrated deployments. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix(athena): enable AWS-managed query results in workgroup The fallback Athena workgroup was missing the managedQueryResultsConfiguration, causing queries to fail with "No output location provided" errors. This change enables AWS-managed query results, which: - Eliminates the need for a dedicated S3 results bucket - Automatically manages storage and cleanup (24-hour retention) - Simplifies infrastructure (no bucket permissions needed) - Aligns with v0.11.0 goal of removing Athena results bucket Also fix trailing comma in wizard phase5 (lint). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * chore: bump version to 0.11.1 * docs: update CHANGELOG for v0.11.1 * docs: highlight automatic workgroup creation feature in CHANGELOG * docs: clarify workgroup change - replaces AWS default, not manual setup --------- Co-authored-by: Claude <[email protected]>
1 parent ec2526a commit 3b30189

24 files changed

+3164
-190
lines changed

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,26 @@
33

44
All notable changes to this project will be documented in this file.
55

6+
## [0.11.1] - 2025-12-27
7+
8+
### Added
9+
10+
- **Custom Athena workgroup for standalone deployments** - Creates webhook-managed workgroup instead of using AWS default, matching the integrated stack behavior and ensuring consistent query results handling
11+
12+
### Fixed
13+
14+
- **Setup wizard UX improvements**
15+
- Removed duplicate standalone deployment prompt
16+
- Removed duplicate disable confirmation and clarified impact
17+
- Clear deployment tracking when configuring integrated mode
18+
- **Status command** - Now waits for ECS rollout completion before exiting
19+
- **Athena workgroup configuration** - Enabled AWS-managed query results in fallback workgroup (fixes "No output location provided" errors)
20+
21+
### Changed
22+
23+
- **Integrated flow** - Improved user experience with clearer prompts and better state management
24+
- **Workgroup resolution** - Automatically uses Quilt-managed workgroup when integrated, creates custom webhook-managed workgroup for standalone deployments (replaces AWS default workgroup)
25+
626
## [0.11.0] - 2025-12-26
727

828
### BREAKING CHANGES

bin/commands/deploy.ts

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
ServiceResolverError,
1010
parseStackArn,
1111
} from "../../lib/utils/service-resolver";
12+
import { extractQuiltResources, getStackResources } from "../../lib/utils/stack-inference";
1213
import { checkCdkBootstrap, createStack } from "../benchling-webhook";
1314
import { XDGConfig } from "../../lib/xdg-config";
1415
import { ProfileConfig, getStackName } from "../../lib/types/config";
@@ -86,6 +87,41 @@ async function checkStackStatus(region: string, stackName: string): Promise<Stac
8687
}
8788
}
8889

90+
async function resolveQuiltAthenaWorkgroup(
91+
stackArn: string,
92+
region: string,
93+
quiltStackName: string,
94+
): Promise<string | undefined> {
95+
try {
96+
const resources = await getStackResources(region, stackArn);
97+
const discovered = extractQuiltResources(resources);
98+
const workgroup = discovered.athenaUserWorkgroup;
99+
100+
if (!workgroup) {
101+
return undefined;
102+
}
103+
104+
const expectedPrefix = `${quiltStackName}-`;
105+
if (!workgroup.startsWith(expectedPrefix)) {
106+
console.log(
107+
chalk.yellow(
108+
`⚠️ Ignoring Athena workgroup '${workgroup}' (expected prefix '${expectedPrefix}')`,
109+
),
110+
);
111+
return undefined;
112+
}
113+
114+
return workgroup;
115+
} catch (error) {
116+
console.log(
117+
chalk.yellow(
118+
`⚠️ Failed to discover Athena workgroup from Quilt stack: ${(error as Error).message}`,
119+
),
120+
);
121+
return undefined;
122+
}
123+
}
124+
89125
// Legacy detection functions removed in v1.0.0
90126
// v1.0.0 uses REST API v1 (not HTTP API v2) with resource policies instead of WAF
91127

@@ -553,16 +589,28 @@ export async function deploy(
553589
process.exit(1);
554590
}
555591

592+
spinner.succeed("Quilt configuration loaded");
593+
594+
spinner.start("Resolving Quilt Athena workgroup...");
595+
const discoveredAthenaWorkgroup = await resolveQuiltAthenaWorkgroup(
596+
stackArn,
597+
deployRegion,
598+
parsed.stackName,
599+
);
600+
if (discoveredAthenaWorkgroup) {
601+
spinner.succeed(`Resolved Athena workgroup: ${discoveredAthenaWorkgroup}`);
602+
} else {
603+
spinner.succeed("No Quilt-managed Athena workgroup found; will create one in webhook stack");
604+
}
605+
556606
// Convert to QuiltServices format for display
557607
const services: QuiltServices = {
558608
packagerQueueUrl: config.quilt.queueUrl,
559609
athenaUserDatabase: config.quilt.database,
560610
quiltWebHost: config.quilt.catalog,
561-
athenaUserWorkgroup: config.quilt.athenaUserWorkgroup,
611+
athenaUserWorkgroup: discoveredAthenaWorkgroup,
562612
};
563613

564-
spinner.succeed("Quilt configuration loaded");
565-
566614
// Build ECR image URI for display
567615
// HARDCODED: Always use the quiltdata AWS account for ECR images
568616
const ecrAccount = "712023778557";
@@ -586,6 +634,8 @@ export async function deploy(
586634
console.log(` ${chalk.bold("Athena Database:")} ${services.athenaUserDatabase}`);
587635
if (services.athenaUserWorkgroup) {
588636
console.log(` ${chalk.bold("Athena Workgroup:")} ${services.athenaUserWorkgroup}`);
637+
} else {
638+
console.log(` ${chalk.bold("Athena Workgroup:")} ${stackName}-athena-workgroup ${chalk.dim("(webhook-managed)")}`);
589639
}
590640
console.log();
591641
console.log(chalk.bold(" Stack Parameters:"));

0 commit comments

Comments
 (0)