spaceforge 1.0.0__tar.gz → 1.1.0__tar.gz

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.
Files changed (57) hide show
  1. {spaceforge-1.0.0 → spaceforge-1.1.0}/PKG-INFO +1 -1
  2. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/sops/plugin.yaml +1 -0
  3. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/wiz/plugin.yaml +1 -0
  4. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/_version_scm.py +3 -3
  5. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/cls.py +2 -0
  6. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/generator.py +64 -18
  7. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/runner.py +3 -3
  8. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/schema.json +6 -1
  9. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_runner.py +3 -3
  10. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_runner_execution.py +3 -3
  11. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge.egg-info/PKG-INFO +1 -1
  12. {spaceforge-1.0.0 → spaceforge-1.1.0}/.github/workflows/ci.yml +0 -0
  13. {spaceforge-1.0.0 → spaceforge-1.1.0}/.github/workflows/release.yml +0 -0
  14. {spaceforge-1.0.0 → spaceforge-1.1.0}/.gitignore +0 -0
  15. {spaceforge-1.0.0 → spaceforge-1.1.0}/LICENSE +0 -0
  16. {spaceforge-1.0.0 → spaceforge-1.1.0}/MANIFEST.in +0 -0
  17. {spaceforge-1.0.0 → spaceforge-1.1.0}/README.md +0 -0
  18. {spaceforge-1.0.0 → spaceforge-1.1.0}/go.mod +0 -0
  19. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/enviroment_manager/plugin.py +0 -0
  20. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/enviroment_manager/plugin.yaml +0 -0
  21. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/enviroment_manager/requirements.txt +0 -0
  22. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/infracost/plugin.py +0 -0
  23. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/infracost/plugin.yaml +0 -0
  24. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/sops/plugin.py +0 -0
  25. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/sops/requirements.txt +0 -0
  26. {spaceforge-1.0.0 → spaceforge-1.1.0}/plugins/wiz/plugin.py +0 -0
  27. {spaceforge-1.0.0 → spaceforge-1.1.0}/pyproject.toml +0 -0
  28. {spaceforge-1.0.0 → spaceforge-1.1.0}/setup.cfg +0 -0
  29. {spaceforge-1.0.0 → spaceforge-1.1.0}/setup.py +0 -0
  30. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/README.md +0 -0
  31. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/__init__.py +0 -0
  32. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/__main__.py +0 -0
  33. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/_version.py +0 -0
  34. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/conftest.py +0 -0
  35. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/plugin.py +0 -0
  36. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/templates/binary_install.sh.j2 +0 -0
  37. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/templates/ensure_spaceforge_and_run.sh.j2 +0 -0
  38. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_cls.py +0 -0
  39. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_generator.py +0 -0
  40. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_generator_binaries.py +0 -0
  41. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_generator_core.py +0 -0
  42. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_generator_hooks.py +0 -0
  43. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_generator_parameters.py +0 -0
  44. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_plugin.py +0 -0
  45. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_plugin_file_operations.py +0 -0
  46. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_plugin_hooks.py +0 -0
  47. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_plugin_inheritance.py +0 -0
  48. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_runner_cli.py +0 -0
  49. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge/test_runner_core.py +0 -0
  50. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge.egg-info/SOURCES.txt +0 -0
  51. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge.egg-info/dependency_links.txt +0 -0
  52. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge.egg-info/entry_points.txt +0 -0
  53. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge.egg-info/not-zip-safe +0 -0
  54. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge.egg-info/requires.txt +0 -0
  55. {spaceforge-1.0.0 → spaceforge-1.1.0}/spaceforge.egg-info/top_level.txt +0 -0
  56. {spaceforge-1.0.0 → spaceforge-1.1.0}/templates.go +0 -0
  57. {spaceforge-1.0.0 → spaceforge-1.1.0}/test.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spaceforge
3
- Version: 1.0.0
3
+ Version: 1.1.0
4
4
  Summary: A Python framework for building Spacelift plugins
5
5
  Home-page: https://github.com/spacelift-io/plugins
6
6
  Author: Spacelift
@@ -137,6 +137,7 @@ contexts:
137
137
 
138
138
  set -e
139
139
 
140
+ export PATH="/mnt/workspace/plugins/plugin_binaries:$PATH"
140
141
  if command -v sops; then
141
142
  echo "sops is already installed."
142
143
  return
@@ -255,6 +255,7 @@ contexts:
255
255
 
256
256
  set -e
257
257
 
258
+ export PATH="/mnt/workspace/plugins/plugin_binaries:$PATH"
258
259
  if command -v wizcli; then
259
260
  echo "wizcli is already installed."
260
261
  return
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.0.0'
32
- __version_tuple__ = version_tuple = (1, 0, 0)
31
+ __version__ = version = '1.1.0'
32
+ __version_tuple__ = version_tuple = (1, 1, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g1a0174591'
34
+ __commit_id__ = commit_id = 'g2812c2227'
@@ -121,6 +121,7 @@ class Context:
121
121
  labels (Optional[List[str]]): Labels associated with the context.
122
122
  env (list): List of variables associated with the context.
123
123
  hooks (dict): Hooks associated with the context.
124
+ priority (optional[int]): The priority of the context, contexts with 0 priority run before contexts with 1 priority.
124
125
  """
125
126
 
126
127
  name_prefix: str
@@ -129,6 +130,7 @@ class Context:
129
130
  mounted_files: Optional[List[MountedFile]] = optional_field
130
131
  hooks: Optional[Dict[HookType, List[str]]] = optional_field
131
132
  labels: Optional[List[str]] = optional_field
133
+ priority: int = 0
132
134
 
133
135
 
134
136
  @pydantic_dataclass
@@ -30,6 +30,41 @@ from .plugin import SpaceforgePlugin
30
30
  static_binary_directory = "/mnt/workspace/plugins/plugin_binaries"
31
31
 
32
32
 
33
+ def _update_context_names_for_priority(contexts: List[Context]) -> List[Context]:
34
+ if len(contexts) <= 1:
35
+ return contexts
36
+
37
+ # Get unique priority values and sort them
38
+ priorities = sorted(set(ctx.priority for ctx in contexts))
39
+
40
+ # Create mapping from priority to letter prefix
41
+ priority_to_letter = {}
42
+
43
+ for i, priority in enumerate(priorities):
44
+ if priority == 0:
45
+ # Priority 0 gets 'Z' (lowest priority = furthest from A)
46
+ letter = "Z"
47
+ else:
48
+ # Higher priority numbers get letters closer to 'A'
49
+ # Reverse the mapping: higher priority index = closer to A
50
+ letter_index = max(0, 25 - i) # Start from Z and work backwards
51
+ letter = chr(ord("A") + letter_index)
52
+
53
+ priority_to_letter[priority] = letter * 5 # Repeat 5 times
54
+
55
+ # Update context names
56
+ for ctx in contexts:
57
+ # Remove existing prefix if it starts with repeated letters
58
+ name = ctx.name_prefix
59
+ if len(name) >= 5 and name[:5].isupper() and len(set(name[:5])) == 1:
60
+ name = name[5:]
61
+
62
+ prefix = priority_to_letter[ctx.priority]
63
+ ctx.name_prefix = prefix + "-" + name
64
+
65
+ return contexts
66
+
67
+
33
68
  class PluginGenerator:
34
69
  """Generates plugin.yaml from a Python plugin class."""
35
70
 
@@ -257,29 +292,39 @@ class PluginGenerator:
257
292
  if self.plugin_class is None:
258
293
  raise ValueError("Plugin class not loaded. Call load_plugin() first.")
259
294
 
260
- contexts = getattr(
261
- self.plugin_class,
262
- "__contexts__",
263
- [
264
- Context(
265
- name_prefix=self.plugin_class.__plugin_name__.lower(),
266
- description=f"Main context for {self.plugin_class.__plugin_name__}",
267
- )
268
- ],
269
- )
295
+ contexts = getattr(self.plugin_class, "__contexts__", [])
270
296
 
271
- if contexts[0].hooks is None:
272
- contexts[0].hooks = {}
273
- if contexts[0].mounted_files is None:
274
- contexts[0].mounted_files = []
275
- if contexts[0].env is None:
276
- contexts[0].env = []
297
+ main_context: Optional[Context] = None
298
+ main_context_found = False
299
+ for context in contexts:
300
+ if context.priority == 0:
301
+ main_context = context
302
+ main_context_found = True
303
+ break
304
+
305
+ if main_context is None:
306
+ main_context = Context(
307
+ name_prefix=self.plugin_class.__plugin_name__.lower(),
308
+ description=f"Main context for {self.plugin_class.__plugin_name__}",
309
+ )
310
+
311
+ if main_context.hooks is None:
312
+ main_context.hooks = {}
313
+ if main_context.mounted_files is None:
314
+ main_context.mounted_files = []
315
+ if main_context.env is None:
316
+ main_context.env = []
277
317
 
278
318
  # Add the hooks and mounted files to the first context
279
- merge(contexts[0].hooks, hooks, strategy=Strategy.TYPESAFE_ADDITIVE)
280
- contexts[0].mounted_files += mounted_files
319
+ merge(main_context.hooks, hooks, strategy=Strategy.TYPESAFE_ADDITIVE)
320
+ main_context.mounted_files += mounted_files
321
+
322
+ # Ensure the main context is first
323
+ if not main_context_found:
324
+ contexts.insert(0, main_context)
281
325
 
282
326
  self._map_variables_to_parameters(contexts)
327
+ contexts = _update_context_names_for_priority(contexts)
283
328
 
284
329
  return contexts
285
330
 
@@ -380,6 +425,7 @@ class PluginGenerator:
380
425
  field.name: getattr(data, field.name)
381
426
  for field in fields(data)
382
427
  if getattr(data, field.name) is not None
428
+ and field.name != "priority"
383
429
  }
384
430
  return self.represent_dict(filtered_dict)
385
431
 
@@ -73,11 +73,11 @@ class PluginRunner:
73
73
  return
74
74
 
75
75
  try:
76
- print(f"[SPACEPY] Running hook: {hook_name}")
76
+ print(f"[SpaceForge] Running hook: {hook_name}")
77
77
  method()
78
- print(f"[SPACEPY] Hook completed: {hook_name}")
78
+ print(f"[SpaceForge] Hook completed: {hook_name}")
79
79
  except Exception as e:
80
- print(f"[SPACEPY] Error running hook '{hook_name}': {e}")
80
+ print(f"[SpaceForge] Error running hook '{hook_name}': {e}")
81
81
  raise
82
82
 
83
83
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$defs": {
3
3
  "Context": {
4
- "description": "A class to represent a context for a plugin.\n\nAttributes:\n name_prefix (str): The name of the context, will be appended with a unique ID.\n description (str): A description of the context.\n labels (Optional[List[str]]): Labels associated with the context.\n env (list): List of variables associated with the context.\n hooks (dict): Hooks associated with the context.",
4
+ "description": "A class to represent a context for a plugin.\n\nAttributes:\n name_prefix (str): The name of the context, will be appended with a unique ID.\n description (str): A description of the context.\n labels (Optional[List[str]]): Labels associated with the context.\n env (list): List of variables associated with the context.\n hooks (dict): Hooks associated with the context.\n priority (optional[int]): The priority of the context, contexts with 0 priority run before contexts with 1 priority.",
5
5
  "properties": {
6
6
  "name_prefix": {
7
7
  "title": "Name Prefix",
@@ -84,6 +84,11 @@
84
84
  }
85
85
  ],
86
86
  "title": "Labels"
87
+ },
88
+ "priority": {
89
+ "default": 0,
90
+ "title": "Priority",
91
+ "type": "integer"
87
92
  }
88
93
  },
89
94
  "required": [
@@ -170,8 +170,8 @@ class NotAPlugin:
170
170
  assert "after_plan" in getattr(runner.plugin_instance, "executed_hooks")
171
171
 
172
172
  # Verify print statements
173
- mock_print.assert_any_call("[SPACEPY] Running hook: after_plan")
174
- mock_print.assert_any_call("[SPACEPY] Hook completed: after_plan")
173
+ mock_print.assert_any_call("[SpaceForge] Running hook: after_plan")
174
+ mock_print.assert_any_call("[SpaceForge] Hook completed: after_plan")
175
175
 
176
176
  def test_run_hook_not_found(self) -> None:
177
177
  """Test running a hook that doesn't exist."""
@@ -210,7 +210,7 @@ class NotAPlugin:
210
210
 
211
211
  # Should print error message
212
212
  mock_print.assert_any_call(
213
- "[SPACEPY] Error running hook 'error_hook': Test error from hook"
213
+ "[SpaceForge] Error running hook 'error_hook': Test error from hook"
214
214
  )
215
215
 
216
216
  def test_run_hook_multiple_hooks(self) -> None:
@@ -61,8 +61,8 @@ class TestRunnerPlugin(SpaceforgePlugin):
61
61
  assert hasattr(runner.plugin_instance, "executed_hooks")
62
62
  assert "after_plan" in getattr(runner.plugin_instance, "executed_hooks")
63
63
 
64
- mock_print.assert_any_call("[SPACEPY] Running hook: after_plan")
65
- mock_print.assert_any_call("[SPACEPY] Hook completed: after_plan")
64
+ mock_print.assert_any_call("[SpaceForge] Running hook: after_plan")
65
+ mock_print.assert_any_call("[SpaceForge] Hook completed: after_plan")
66
66
 
67
67
  def test_should_print_error_when_hook_method_not_found(
68
68
  self, test_plugin_file: str
@@ -125,7 +125,7 @@ class ErrorPlugin(SpaceforgePlugin):
125
125
  runner.run_hook("error_hook")
126
126
 
127
127
  mock_print.assert_any_call(
128
- "[SPACEPY] Error running hook 'error_hook': Test error from hook"
128
+ "[SpaceForge] Error running hook 'error_hook': Test error from hook"
129
129
  )
130
130
 
131
131
  def test_should_execute_multiple_hooks_maintaining_state(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spaceforge
3
- Version: 1.0.0
3
+ Version: 1.1.0
4
4
  Summary: A Python framework for building Spacelift plugins
5
5
  Home-page: https://github.com/spacelift-io/plugins
6
6
  Author: Spacelift
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes