Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Sem 115 feature perproject configurable proxy definitions ssh socks - #4123

Open
befika wants to merge 18 commits into
semaphoreui:developfrom
befika:sem-115-feature-perproject-configurable-proxy-definitions-ssh-socks
Open

Sem 115 feature perproject configurable proxy definitions ssh socks#4123
befika wants to merge 18 commits into
semaphoreui:developfrom
befika:sem-115-feature-perproject-configurable-proxy-definitions-ssh-socks

Conversation

@befika

@befika befika commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added project-level SSH proxy management, including creation, editing, deletion, validation, and reference viewing.
    • Inventories can now use a selected SSH proxy.
    • Ansible-based tasks support proxy routing and proxy-specific SSH keys.
    • Added proxy navigation and project API endpoints.
  • Backup and Restore

    • Backups now include proxy configurations and preserve inventory-to-proxy associations during restoration.
  • Documentation

    • Expanded API reference documentation for proxy operations and inventory proxy references.

befika added 3 commits August 5, 2026 11:30
- Introduced Proxy struct and related Backup types to handle SSH jump hosts.
- Updated InventoryService to fetch and deserialize proxy SSH keys.
- Enhanced LocalExecutor to manage proxy key installations and SSH arguments.
- Added new API endpoints for managing proxies within projects, including CRUD operations.
- Implemented workflow management features, allowing creation, retrieval, and execution of workflows.
- Updated Swagger API documentation to reflect new proxy and workflow definitions.
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change adds project SSH proxy support across storage, APIs, backups, task execution, and the web UI. It also expands the Swagger specification for options, workflows, runners, templates, views, and related endpoints.

Changes

SSH proxy support

Layer / File(s) Summary
Proxy model and persistence
db/Proxy.go, db/sql/proxy.go, db/sql/migrations/*, db/Inventory.go, db/Store.go
Adds validated SSH proxy records, project-scoped SQL operations, migration support, and nullable inventory proxy references.
Proxy API
api/projects/proxies.go, api/router.go, api-docs.yml, .dredd/hooks/*
Adds proxy collection and item endpoints, reference lookup, middleware loading, validation, event logging, and API test capabilities.
Backup and restore
services/project/types.go, services/project/backup.go, services/project/restore.go, services/project/backup_test.go
Serializes proxies and inventory references, validates backup proxy data, restores proxies before inventories, and tests round-trip preservation.
SSH proxy task execution
services/server/inventory_svc.go, services/tasks/*
Loads proxy and SSH key data, installs proxy keys, generates ProxyJump arguments, passes them to Ansible, and cleans up key installations.
Proxy management UI
web/src/views/project/Proxies.vue, web/src/components/ProxyForm.vue, web/src/components/InventoryForm.vue, web/src/router/index.js, web/src/App.vue, web/src/lang/en.js
Adds project proxy navigation, routing, CRUD controls, proxy configuration fields, inventory selection, and localization strings.

API specification updates

Layer / File(s) Summary
Additional API specification changes
web/public/swagger/api-docs.yml
Documents proxies, options, workflows, runners, templates, views, task controls, and related parameters. Selected cluster and invitation definitions are commented out.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ProxiesView
  participant ProxyAPI
  participant SqlDb
  User->>ProxiesView: Create or edit proxy
  ProxiesView->>ProxyAPI: Submit proxy request
  ProxyAPI->>SqlDb: CreateProxy or UpdateProxy
  SqlDb-->>ProxyAPI: Proxy result
  ProxyAPI-->>ProxiesView: JSON response
  ProxiesView-->>User: Refresh proxy list
Loading
sequenceDiagram
  participant Inventory
  participant LocalExecutor
  participant Ansible
  Inventory->>LocalExecutor: Provide proxy configuration
  LocalExecutor->>Ansible: Pass ProxyJump SSH arguments
  Ansible-->>LocalExecutor: Run inventory tasks
  LocalExecutor->>LocalExecutor: Clean up proxy key
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title refers to proxy definitions but uses acronyms and protocol names that obscure the main change. The PR implements per-project configurable SSH proxy support across the full stack. Use a clearer title that describes the feature without acronyms. Example: 'Add per-project SSH proxy configuration support' or 'Implement project-scoped proxy definitions'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
db/sql/inventory.go (1)

45-55: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Verify proxy ownership before persisting ProxyID.

Both methods persist inventory.ProxyID without verifying that the proxy belongs to inventory.ProjectID. The foreign key accepts a proxy from another project because it checks only the proxy ID. This creates an invalid cross-project association.

Before each write, resolve a non-nil ProxyID with GetProxy(inventory.ProjectID, *inventory.ProxyID) and return its error. Add create and update tests that reject a proxy from another project.

Also applies to: 68-81

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@db/sql/inventory.go` around lines 45 - 55, Before persisting ProxyID in both
inventory create and update methods, validate non-nil values by calling GetProxy
with inventory.ProjectID and the dereferenced proxy ID, returning any error
before the write. Preserve nil ProxyID handling, and add create/update tests
confirming proxies from another project are rejected.
🧹 Nitpick comments (2)
web/src/views/project/Proxies.vue (2)

67-76: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Gate the edit and delete actions with the same permission as the create button.

Line 43 hides the create button behind can(USER_PERMISSIONS.manageProjectResources). The edit and delete buttons carry no guard. A user without the permission sees actions that the API rejects.

♻️ Proposed fix for consistent gating
       <template v-slot:item.actions="{ item }">
-        <v-btn-toggle dense :value-comparator="() => false">
+        <v-btn-toggle
+          dense
+          :value-comparator="() => false"
+          v-if="can(USER_PERMISSIONS.manageProjectResources)"
+        >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/views/project/Proxies.vue` around lines 67 - 76, Gate the edit and
delete action controls in the item.actions slot with the same
can(USER_PERMISSIONS.manageProjectResources) permission check used by the create
button. Ensure users lacking this permission cannot see either action while
preserving the existing askDeleteItem and editItem handlers for authorized
users.

3-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Localize the dialog title and the object title.

Line 6 builds the title with the literal English word Proxy. Line 23 passes the literal proxy as object-title. Both strings appear in the UI and bypass vue-i18n. The newProxy and proxies keys already exist in web/src/lang/en.js.

♻️ Proposed fix to use translation keys
       :save-button-text="itemId === 'new' ? $t('create') : $t('save')"
-      :title="`${itemId === 'new' ? $t('nnew') : $t('edit')} Proxy`"
+      :title="itemId === 'new' ? $t('newProxy') : $t('editProxy')"

Add the missing key to web/src/lang/en.js:

  editProxy: 'Edit Proxy',
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/views/project/Proxies.vue` around lines 3 - 27, Update the EditDialog
title and ObjectRefsDialog object-title in Proxies.vue to use the existing
vue-i18n proxy translation keys instead of the literal “Proxy” and “proxy”
strings; add the editProxy key to en.js if needed and preserve the existing
create/edit title behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api-docs.yml`:
- Around line 2978-2991: Add the missing ObjectReferrers definition to
api-docs.yml, matching the schema expected by the
/project/{project_id}/proxies/{proxy_id}/refs response, and duplicate the same
definition in web/public/swagger/api-docs.yml so both
`#/definitions/ObjectReferrers` references resolve.

In `@db/sql/migrations/v2.20.2.sql`:
- Around line 1-13: Update the project__proxy table definition in migration
v2.20.2 to enforce UNIQUE(project_id, name), then add a regression test covering
creation of two proxies with the same name in one project and asserting the
duplicate is rejected.

In `@services/project/backup.go`:
- Around line 369-379: Update the backup name-normalization flow in
makeUniqueNames to include b.proxies, ensuring each project’s proxy names are
unique before BackupProxy serialization and restore lookup via findEntityByName.
Preserve the existing naming behavior for other entities and ensure the
normalized names are used by BackupProxy.Name.

In `@services/tasks/local_executor_inventory.go`:
- Around line 57-65: Update getInventorySSHCommonArgs to generate a unique SSH
config alias for the proxy jump host containing its HostName, User, Port, and
proxy SSHAgent SocketFile, then use that alias in ProxyJump instead of applying
IdentityAgent to destination options. In
services/tasks/local_executor_inventory.go:57-65 implement the jump-host
configuration; in services/tasks/local_executor_test.go:74-85 add coverage with
a proxy SSH key asserting IdentityAgent is configured on the jump-host alias
rather than only on destination options.

In `@web/src/components/ProxyForm.vue`:
- Around line 47-56: Update the ProxyForm save flow to normalize an empty port
value to null before submitting the request, and ensure zero is rejected by the
port validation rule. Locate the relevant save handler and port field rules in
ProxyForm.vue; preserve valid ports from 1 through 65535 and keep the nullable
API contract intact.

In `@web/src/views/project/Proxies.vue`:
- Around line 57-61: Update the item.host slot template to render a clear
separator between the host text and the conditional port value, while preserving
the existing user@host formatting and omitting the separator when item.port is
absent.

---

Outside diff comments:
In `@db/sql/inventory.go`:
- Around line 45-55: Before persisting ProxyID in both inventory create and
update methods, validate non-nil values by calling GetProxy with
inventory.ProjectID and the dereferenced proxy ID, returning any error before
the write. Preserve nil ProxyID handling, and add create/update tests confirming
proxies from another project are rejected.

---

Nitpick comments:
In `@web/src/views/project/Proxies.vue`:
- Around line 67-76: Gate the edit and delete action controls in the
item.actions slot with the same can(USER_PERMISSIONS.manageProjectResources)
permission check used by the create button. Ensure users lacking this permission
cannot see either action while preserving the existing askDeleteItem and
editItem handlers for authorized users.
- Around line 3-27: Update the EditDialog title and ObjectRefsDialog
object-title in Proxies.vue to use the existing vue-i18n proxy translation keys
instead of the literal “Proxy” and “proxy” strings; add the editProxy key to
en.js if needed and preserve the existing create/edit title behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b4c6dab7-6e57-42d4-852e-260d67f51407

📥 Commits

Reviewing files that changed from the base of the PR and between ff0cf4c and 5e35f33.

📒 Files selected for processing (29)
  • api-docs.yml
  • api/projects/proxies.go
  • api/router.go
  • db/BackupEntity.go
  • db/Event.go
  • db/Inventory.go
  • db/Migration.go
  • db/Proxy.go
  • db/Proxy_test.go
  • db/Store.go
  • db/sql/inventory.go
  • db/sql/migrations/v2.20.2.err.sql
  • db/sql/migrations/v2.20.2.sql
  • db/sql/proxy.go
  • services/project/backup.go
  • services/project/backup_test.go
  • services/project/restore.go
  • services/project/types.go
  • services/server/inventory_svc.go
  • services/tasks/local_executor.go
  • services/tasks/local_executor_inventory.go
  • services/tasks/local_executor_test.go
  • web/public/swagger/api-docs.yml
  • web/src/App.vue
  • web/src/components/InventoryForm.vue
  • web/src/components/ProxyForm.vue
  • web/src/lang/en.js
  • web/src/router/index.js
  • web/src/views/project/Proxies.vue

Comment thread api-docs.yml Outdated
Comment thread db/sql/migrations/v2.20.2.sql Outdated
Comment thread services/project/backup.go
Comment thread services/tasks/local_executor_inventory.go Outdated
Comment thread web/src/components/ProxyForm.vue
Comment thread web/src/views/project/Proxies.vue

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
db/Proxy.go (1)

72-86: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Handle already-bracketed IPv6 hosts before net.JoinHostPort.

Destination passes p.Host directly to net.JoinHostPort. A host such as [2001:db8::1] contains a colon, so using a port produces [[2001:db8::1]]:2222. Normalize one outer bracket pair before joining, or reject bracketed input, and add a regression test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@db/Proxy.go` around lines 72 - 86, Update Proxy.Destination to normalize a
single outer bracket pair from p.Host before calling net.JoinHostPort, so
already-bracketed IPv6 hosts produce exactly one bracket pair with a port.
Preserve existing user-prefix and unported-host behavior, and add a regression
test covering a bracketed IPv6 host with a port.

Source: MCP tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@db/Proxy.go`:
- Around line 59-61: Update proxy validation around the SSHKeyID check to
resolve the referenced access key using proxy.ProjectID, require it to be an
AccessKeySSH key, and reject missing, cross-project, or mismatched key types
before persistence. Apply this validation to both CreateProxy and UpdateProxy,
and add tests covering valid keys and rejected invalid or cross-project keys.

---

Outside diff comments:
In `@db/Proxy.go`:
- Around line 72-86: Update Proxy.Destination to normalize a single outer
bracket pair from p.Host before calling net.JoinHostPort, so already-bracketed
IPv6 hosts produce exactly one bracket pair with a port. Preserve existing
user-prefix and unported-host behavior, and add a regression test covering a
bracketed IPv6 host with a port.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: acf993ef-00d9-4156-9864-d9439412725e

📥 Commits

Reviewing files that changed from the base of the PR and between b04b306 and c7102d7.

📒 Files selected for processing (2)
  • db/Proxy.go
  • services/project/backup_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • services/project/backup_test.go

Comment thread db/Proxy.go
@befika
befika marked this pull request as draft August 5, 2026 10:37
befika and others added 6 commits August 5, 2026 14:40
…perproject-configurable-proxy-definitions-ssh-socks
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…ns-ssh-socks' of github.com:befika/semaphore into sem-115-feature-perproject-configurable-proxy-definitions-ssh-socks
@befika
befika marked this pull request as ready for review August 5, 2026 13:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/src/components/ProxyForm.vue`:
- Line 51: Update the port validation in ProxyForm.vue so the ProxyForm port
field rejects fractional values like 22.5 before submission; adjust the rule
attached to the port input to require an integer (or convert the value to an
integer before saving) while still allowing empty/null values and the existing
1–65535 range, and update the port input itself to use type="number" with
step="1" so it matches the nullable integer contract.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: de66d557-c720-4243-997c-853feb668e54

📥 Commits

Reviewing files that changed from the base of the PR and between c7102d7 and ed3842d.

📒 Files selected for processing (12)
  • .dredd/hooks/capabilities.go
  • .dredd/hooks/main.go
  • api-docs.yml
  • api/projects/proxies.go
  • db/Store.go
  • db/sql/migrations/v2.20.2.sql
  • db/sql/proxy_test.go
  • services/tasks/local_executor.go
  • services/tasks/local_executor_test.go
  • web/public/swagger/api-docs.yml
  • web/src/components/ProxyForm.vue
  • web/src/lang/en.js
🚧 Files skipped from review as they are similar to previous changes (7)
  • web/src/lang/en.js
  • db/sql/migrations/v2.20.2.sql
  • services/tasks/local_executor.go
  • services/tasks/local_executor_test.go
  • api-docs.yml
  • api/projects/proxies.go
  • web/public/swagger/api-docs.yml

Comment thread web/src/components/ProxyForm.vue
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds project-scoped SSH proxy (jump host) support across the Semaphore stack (DB/API/UI/executor) so inventories can route SSH connections through a selected proxy, and the configuration survives backup/restore.

Changes:

  • Introduces a new Proxy model + persistence (SQL migration, store methods) and exposes CRUD + refs endpoints under /api/project/{project_id}/proxies.
  • Adds UI for managing proxies and selecting a proxy on inventories.
  • Updates the Ansible local executor to pass proxy-related SSH options, and extends backup/restore + API docs/test hooks accordingly.

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
web/src/views/project/Proxies.vue New project Proxies list + edit/delete dialogs
web/src/router/index.js Adds /project/:projectId/proxies route
web/src/lang/en.js Adds i18n strings for proxies + inventory proxy selector
web/src/components/ProxyForm.vue New proxy create/edit form
web/src/components/InventoryForm.vue Adds proxy selection field and loads proxies
web/src/App.vue Adds “Proxies” nav entry
web/public/swagger/api-docs.yml Documents proxy endpoints/models (and other API additions)
services/tasks/local_executor.go Passes --ssh-common-args when inventory has a proxy
services/tasks/local_executor_test.go Adds unit tests for proxy SSH args and playbook args
services/tasks/local_executor_inventory.go Installs proxy key agent + builds SSH common args
services/server/inventory_svc.go Loads inventory proxy (and decrypts proxy SSH key)
services/project/types.go Extends backup schema with proxies + inventory-to-proxy reference
services/project/restore.go Restores proxies before inventories; validates proxy references
services/project/backup.go Includes proxies in backups; serializes inventory proxy by name
services/project/backup_test.go Adds backup/restore round-trip test for proxies
db/Store.go Adds proxy CRUD/ref methods to store interface + proxy object metadata
db/sql/proxy.go SQL store implementation for proxy CRUD + refs
db/sql/proxy_test.go Tests proxy key validation (same project + SSH-only)
db/sql/migrations/v2.20.2.sql Adds project__proxy and inventory.proxy_id
db/sql/migrations/v2.20.2.err.sql Down migration for proxy table/column
db/sql/inventory.go Persists proxy_id in inventory create/update
db/Proxy.go Adds Proxy model, validation, and ProxyJump destination rendering
db/Proxy_test.go Tests proxy validation and destination formatting
db/Migration.go Registers migration 2.20.2
db/Inventory.go Adds ProxyID/Proxy fields to inventory
db/Event.go Adds EventProxy object type
db/BackupEntity.go Adds backup entity helpers for Proxy
api/router.go Wires proxy routes + middleware
api/projects/proxies.go Implements proxy CRUD + refs handlers
api-docs.yml Documents proxy endpoints/models (and other API additions)
.dredd/hooks/main.go Adds Dredd hooks for proxy endpoints
.dredd/hooks/capabilities.go Adds proxy capability setup and request body/path substitution

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread services/tasks/local_executor_inventory.go Outdated
@befika
befika marked this pull request as draft August 12, 2026 08:41
befika added 2 commits August 12, 2026 11:42
…ns-ssh-socks' of github.com:befika/semaphore into sem-115-feature-perproject-configurable-proxy-definitions-ssh-socks
@befika
befika marked this pull request as ready for review August 12, 2026 09:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Proxy routing currently has command-injection risks, remote-runner omissions, and several configurations that silently bypass or fail to use the selected proxy.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 56/56 changed files
  • Comments generated: 17
  • Review effort level: Balanced

Comment thread db/Proxy.go Outdated
Comment thread db/Proxy.go Outdated
Comment thread db_lib/Proxy.go Outdated
Comment thread api-docs.yml
Comment thread api/projects/proxies.go
Comment thread services/project/restore.go
Comment thread services/tasks/local_executor_inventory.go Outdated
Comment thread web/public/swagger/api-docs.yml Outdated
Comment thread web/src/components/ProxyForm.vue
Comment thread cli/cmd/proxy_connect.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants