recce-cloud 1.33.1__py3-none-any.whl → 1.34.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,8 +19,8 @@ from recce_cloud.config.project_config import get_project_binding
19
19
  class ResolvedConfig:
20
20
  """Resolved configuration with source information."""
21
21
 
22
- org: str
23
- project: str
22
+ org_id: str
23
+ project_id: str
24
24
  source: str # "cli", "env", "config"
25
25
 
26
26
 
@@ -30,6 +30,26 @@ class ConfigurationError(Exception):
30
30
  pass
31
31
 
32
32
 
33
+ def _validate_numeric_id(value: str, field_name: str, source: str) -> None:
34
+ """
35
+ Validate that a value is a numeric ID.
36
+
37
+ Args:
38
+ value: The value to validate.
39
+ field_name: Name of the field (for error messages).
40
+ source: Source of the value (for error messages).
41
+
42
+ Raises:
43
+ ConfigurationError: If the value is not a numeric ID.
44
+ """
45
+ if not value.isdigit():
46
+ raise ConfigurationError(
47
+ f"Invalid {field_name}: '{value}' (from {source}). "
48
+ f"The API requires numeric IDs, not slugs. "
49
+ f"Run 'recce-cloud init' to bind this directory to a project with proper IDs."
50
+ )
51
+
52
+
33
53
  def resolve_config(
34
54
  cli_org: Optional[str] = None,
35
55
  cli_project: Optional[str] = None,
@@ -45,32 +65,40 @@ def resolve_config(
45
65
  4. Error if nothing found
46
66
 
47
67
  Args:
48
- cli_org: Organization from CLI flag.
49
- cli_project: Project from CLI flag.
68
+ cli_org: Organization ID from CLI flag.
69
+ cli_project: Project ID from CLI flag.
50
70
  project_dir: Project directory for local config lookup.
51
71
 
52
72
  Returns:
53
- ResolvedConfig with org, project, and source.
73
+ ResolvedConfig with org_id, project_id, and source.
54
74
 
55
75
  Raises:
56
76
  ConfigurationError: If org/project cannot be resolved.
57
77
  """
58
78
  # Priority 1: CLI flags
59
79
  if cli_org and cli_project:
60
- return ResolvedConfig(org=cli_org, project=cli_project, source="cli")
80
+ _validate_numeric_id(cli_org, "org", "CLI flag --org")
81
+ _validate_numeric_id(cli_project, "project", "CLI flag --project")
82
+ return ResolvedConfig(org_id=cli_org, project_id=cli_project, source="cli")
61
83
 
62
84
  # Priority 2: Environment variables
63
85
  env_org = os.environ.get("RECCE_ORG")
64
86
  env_project = os.environ.get("RECCE_PROJECT")
65
87
  if env_org and env_project:
66
- return ResolvedConfig(org=env_org, project=env_project, source="env")
88
+ _validate_numeric_id(env_org, "org", "environment variable RECCE_ORG")
89
+ _validate_numeric_id(env_project, "project", "environment variable RECCE_PROJECT")
90
+ return ResolvedConfig(org_id=env_org, project_id=env_project, source="env")
67
91
 
68
92
  # Priority 3: Local config file
69
93
  binding = get_project_binding(project_dir)
70
94
  if binding:
95
+ org_id = binding["org_id"]
96
+ project_id = binding["project_id"]
97
+ _validate_numeric_id(org_id, "org_id", "config file")
98
+ _validate_numeric_id(project_id, "project_id", "config file")
71
99
  return ResolvedConfig(
72
- org=binding["org"],
73
- project=binding["project"],
100
+ org_id=org_id,
101
+ project_id=project_id,
74
102
  source="config",
75
103
  )
76
104
 
@@ -81,19 +109,19 @@ def resolve_config(
81
109
  )
82
110
 
83
111
 
84
- def resolve_org(
112
+ def resolve_org_id(
85
113
  cli_org: Optional[str] = None,
86
114
  project_dir: Optional[str] = None,
87
115
  ) -> Optional[str]:
88
116
  """
89
- Resolve organization from multiple sources.
117
+ Resolve organization ID from multiple sources.
90
118
 
91
119
  Args:
92
- cli_org: Organization from CLI flag.
120
+ cli_org: Organization ID from CLI flag.
93
121
  project_dir: Project directory for local config lookup.
94
122
 
95
123
  Returns:
96
- Organization name/slug, or None if not found.
124
+ Organization ID, or None if not found.
97
125
  """
98
126
  if cli_org:
99
127
  return cli_org
@@ -104,24 +132,24 @@ def resolve_org(
104
132
 
105
133
  binding = get_project_binding(project_dir)
106
134
  if binding:
107
- return binding["org"]
135
+ return binding["org_id"]
108
136
 
109
137
  return None
110
138
 
111
139
 
112
- def resolve_project(
140
+ def resolve_project_id(
113
141
  cli_project: Optional[str] = None,
114
142
  project_dir: Optional[str] = None,
115
143
  ) -> Optional[str]:
116
144
  """
117
- Resolve project from multiple sources.
145
+ Resolve project ID or slug from multiple sources.
118
146
 
119
147
  Args:
120
- cli_project: Project from CLI flag.
148
+ cli_project: Project ID or slug from CLI flag.
121
149
  project_dir: Project directory for local config lookup.
122
150
 
123
151
  Returns:
124
- Project name/slug, or None if not found.
152
+ Project ID or slug, or None if not found.
125
153
  """
126
154
  if cli_project:
127
155
  return cli_project
@@ -132,6 +160,6 @@ def resolve_project(
132
160
 
133
161
  binding = get_project_binding(project_dir)
134
162
  if binding:
135
- return binding["project"]
163
+ return binding["project_id"]
136
164
 
137
165
  return None
recce_cloud/delete.py CHANGED
@@ -65,7 +65,7 @@ def delete_with_platform_apis(console, token: str, ci_info, prod: bool):
65
65
  sys.exit(2)
66
66
 
67
67
  # Determine session type
68
- session_type = "prod" if prod else "cr"
68
+ session_type = "prod" if prod else "pr"
69
69
 
70
70
  # Delete session
71
71
  console.rule("Deleting session", style="blue")
@@ -73,14 +73,14 @@ def delete_with_platform_apis(console, token: str, ci_info, prod: bool):
73
73
  # Determine what to display based on session type
74
74
  if session_type == "prod":
75
75
  console.print("Deleting production/base session...")
76
- elif session_type == "cr":
77
- console.print(f"Deleting PR/MR session (CR #{ci_info.cr_number})...")
76
+ elif session_type == "pr":
77
+ console.print(f"Deleting PR/MR session (PR #{ci_info.pr_number})...")
78
78
  else:
79
79
  console.print("Deleting session...")
80
80
 
81
81
  try:
82
82
  delete_response = client.delete_session(
83
- cr_number=ci_info.cr_number,
83
+ pr_number=ci_info.pr_number,
84
84
  session_type=session_type,
85
85
  )
86
86
 
@@ -105,7 +105,7 @@ def delete_with_platform_apis(console, token: str, ci_info, prod: bool):
105
105
  console.rule("Deleted Successfully", style="green")
106
106
  console.print(f'Deleted session ID "{session_id}" from Recce Cloud')
107
107
 
108
- if ci_info.cr_url:
109
- console.print(f"Change request: {ci_info.cr_url}")
108
+ if ci_info.pr_url:
109
+ console.print(f"Pull request: {ci_info.pr_url}")
110
110
 
111
111
  sys.exit(0)
recce_cloud/download.py CHANGED
@@ -181,14 +181,14 @@ def download_with_platform_apis(console, token: str, ci_info, target_path: str,
181
181
  # Determine what to display based on session type
182
182
  if ci_info.session_type == "prod":
183
183
  console.print("Looking for production/base session...")
184
- elif ci_info.session_type == "cr":
185
- console.print(f"Looking for PR/MR session (CR #{ci_info.cr_number})...")
184
+ elif ci_info.session_type == "pr":
185
+ console.print(f"Looking for PR/MR session (PR #{ci_info.pr_number})...")
186
186
  else:
187
187
  console.print("Looking for session...")
188
188
 
189
189
  try:
190
190
  download_response = client.get_session_download_urls(
191
- cr_number=ci_info.cr_number,
191
+ pr_number=ci_info.pr_number,
192
192
  session_type=ci_info.session_type,
193
193
  )
194
194
 
@@ -224,7 +224,7 @@ def download_with_platform_apis(console, token: str, ci_info, target_path: str,
224
224
  console.print(f'Downloaded dbt artifacts from Recce Cloud for session ID "{session_id}"')
225
225
  console.print(f'Artifacts saved to: "{os.path.abspath(target_path)}"')
226
226
 
227
- if ci_info.cr_url:
228
- console.print(f"Change request: {ci_info.cr_url}")
227
+ if ci_info.pr_url:
228
+ console.print(f"Pull request: {ci_info.pr_url}")
229
229
 
230
230
  sys.exit(0)