Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @SocketDev/eng
* @SocketDev/customer-engineering
3 changes: 2 additions & 1 deletion .github/workflows/pr-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: '3.x'
python-version: '3.13'

# Install all dependencies from pyproject.toml
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "virtualenv<20.36"
pip install hatchling==1.27.0 hatch==1.14.0

- name: Inject full dynamic version
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3
with:
python-version: '3.x'
python-version: '3.13'

# Install all dependencies from pyproject.toml
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "virtualenv<20.36"
pip install hatchling==1.27.0 hatch==1.14.0

- name: Get Version
Expand Down
27 changes: 18 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ These examples are production-ready and include best practices for each platform

## Monorepo Workspace Support

> **Note:** If you're looking to associate a scan with a named Socket workspace (e.g. because your repo is identified as `org/repo`), see the [`--workspace` flag](#repository) instead. The `--workspace-name` flag described in this section is an unrelated monorepo feature.

The Socket CLI supports scanning specific workspaces within monorepo structures while preserving git context from the repository root. This is useful for organizations that maintain multiple applications or services in a single repository.

### Key Features
Expand Down Expand Up @@ -114,7 +116,7 @@ This will simultaneously generate:
## Usage

```` shell
socketcli [-h] [--api-token API_TOKEN] [--repo REPO] [--repo-is-public] [--branch BRANCH] [--integration {api,github,gitlab,azure,bitbucket}]
socketcli [-h] [--api-token API_TOKEN] [--repo REPO] [--workspace WORKSPACE] [--repo-is-public] [--branch BRANCH] [--integration {api,github,gitlab,azure,bitbucket}]
[--owner OWNER] [--pr-number PR_NUMBER] [--commit-message COMMIT_MESSAGE] [--commit-sha COMMIT_SHA] [--committers [COMMITTERS ...]]
[--target-path TARGET_PATH] [--sbom-file SBOM_FILE] [--license-file-name LICENSE_FILE_NAME] [--save-submitted-files-list SAVE_SUBMITTED_FILES_LIST]
[--save-manifest-tar SAVE_MANIFEST_TAR] [--files FILES] [--sub-path SUB_PATH] [--workspace-name WORKSPACE_NAME]
Expand All @@ -138,14 +140,21 @@ If you don't want to provide the Socket API Token every time then you can use th
| --api-token | False | | Socket Security API token (can also be set via SOCKET_SECURITY_API_TOKEN env var) |

#### Repository
| Parameter | Required | Default | Description |
|:-----------------|:---------|:--------|:------------------------------------------------------------------------|
| --repo | False | *auto* | Repository name in owner/repo format (auto-detected from git remote) |
| --repo-is-public | False | False | If set, flags a new repository creation as public. Defaults to false. |
| --integration | False | api | Integration type (api, github, gitlab, azure, bitbucket) |
| --owner | False | | Name of the integration owner, defaults to the socket organization slug |
| --branch | False | *auto* | Branch name (auto-detected from git) |
| --committers | False | *auto* | Committer(s) to filter by (auto-detected from git commit) |
| Parameter | Required | Default | Description |
|:-----------------|:---------|:--------|:------------------------------------------------------------------------------------------------------------------|
| --repo | False | *auto* | Repository name in owner/repo format (auto-detected from git remote) |
| --workspace | False | | The Socket workspace to associate the scan with (e.g. `my-org` in `my-org/my-repo`). See note below. |
| --repo-is-public | False | False | If set, flags a new repository creation as public. Defaults to false. |
| --integration | False | api | Integration type (api, github, gitlab, azure, bitbucket) |
| --owner | False | | Name of the integration owner, defaults to the socket organization slug |
| --branch | False | *auto* | Branch name (auto-detected from git) |
| --committers | False | *auto* | Committer(s) to filter by (auto-detected from git commit) |

> **`--workspace` vs `--workspace-name`** — these are two distinct flags for different purposes:
>
> - **`--workspace <string>`** maps to the Socket API's `workspace` query parameter on `CreateOrgFullScan`. Use it when your repository belongs to a named Socket workspace (e.g. an org with multiple workspace groups). Example: `--repo my-repo --workspace my-org`. Without this flag, scans are created without workspace context and may not appear under the correct workspace in the Socket dashboard.
>
> - **`--workspace-name <string>`** is a monorepo feature. It appends a suffix to the repository slug to create a unique name in Socket (e.g. `my-repo-frontend`). It must always be paired with `--sub-path` and has nothing to do with the API `workspace` field. See [Monorepo Workspace Support](#monorepo-workspace-support) below.

#### Pull Request and Commit
| Parameter | Required | Default | Description |
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build-backend = "hatchling.build"

[project]
name = "socketsecurity"
version = "2.2.73"
version = "2.2.74"
requires-python = ">= 3.10"
license = {"file" = "LICENSE"}
dependencies = [
Expand All @@ -16,7 +16,7 @@ dependencies = [
'GitPython',
'packaging',
'python-dotenv',
"socketdev>=3.0.29,<4.0.0",
"socketdev>=3.0.31,<4.0.0",
"bs4>=0.0.2",
"markdown>=3.10",
]
Expand Down
2 changes: 1 addition & 1 deletion socketsecurity/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__author__ = 'socket.dev'
__version__ = '2.2.73'
__version__ = '2.2.74'
USER_AGENT = f'SocketPythonCLI/{__version__}'
8 changes: 8 additions & 0 deletions socketsecurity/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class CliConfig:
save_manifest_tar: Optional[str] = None
sub_paths: List[str] = field(default_factory=list)
workspace_name: Optional[str] = None
workspace: Optional[str] = None
# Reachability Flags
reach: bool = False
reach_version: Optional[str] = None
Expand Down Expand Up @@ -145,6 +146,7 @@ def from_args(cls, args_list: Optional[List[str]] = None) -> 'CliConfig':
'save_manifest_tar': args.save_manifest_tar,
'sub_paths': args.sub_paths or [],
'workspace_name': args.workspace_name,
'workspace': args.workspace,
'slack_webhook': args.slack_webhook,
'reach': args.reach,
'reach_version': args.reach_version,
Expand Down Expand Up @@ -256,6 +258,12 @@ def create_argument_parser() -> argparse.ArgumentParser:
help="Repository name in owner/repo format",
required=False
)
repo_group.add_argument(
"--workspace",
metavar="<string>",
help="The workspace in the Socket Organization that the repository is in to associate with the full scan.",
required=False
)
repo_group.add_argument(
"--repo-is-public",
dest="repo_is_public",
Expand Down
3 changes: 2 additions & 1 deletion socketsecurity/socketcli.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,8 @@ def main_code():
make_default_branch=is_default_branch,
set_as_pending_head=is_default_branch,
tmp=False,
scan_type='socket_tier1' if config.reach else 'socket'
scan_type='socket_tier1' if config.reach else 'socket',
workspace=config.workspace or None,
)

params.include_license_details = not config.exclude_license_details
Expand Down
23 changes: 22 additions & 1 deletion tests/unit/test_cli_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,25 @@ def test_strict_blocking_with_disable_blocking(self):
"--disable-blocking"
])
assert config.strict_blocking is True
assert config.disable_blocking is True
assert config.disable_blocking is True

def test_workspace_flag(self):
"""Test that --workspace is parsed and stored correctly."""
config = CliConfig.from_args(["--api-token", "test", "--workspace", "my-workspace"])
assert config.workspace == "my-workspace"

def test_workspace_default_is_none(self):
"""Test that workspace defaults to None when not supplied."""
config = CliConfig.from_args(["--api-token", "test"])
assert config.workspace is None

def test_workspace_is_independent_of_workspace_name(self):
"""--workspace and --workspace-name are distinct flags with distinct purposes."""
config = CliConfig.from_args([
"--api-token", "test",
"--workspace", "my-workspace",
"--sub-path", ".",
"--workspace-name", "monorepo-suffix",
])
assert config.workspace == "my-workspace"
assert config.workspace_name == "monorepo-suffix"
10 changes: 5 additions & 5 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading