diff --git a/.hooks/version-check.py b/.hooks/version-check.py index f639739..b1a0189 100755 --- a/.hooks/version-check.py +++ b/.hooks/version-check.py @@ -11,7 +11,7 @@ - docs/pre-commit-hook.md (Docker build tags) Pattern matching: -- GitHub Actions: SocketDev/socket-basics@vX.X.X -> @vNEW_VERSION +- GitHub Actions: SocketDev/socket-basics@X.X.X -> @NEW_VERSION (no v prefix) - Docker builds: docker build -t IMAGE_NAME -> docker build -t IMAGE_NAME:NEW_VERSION Usage: @@ -39,8 +39,8 @@ VERSION_PATTERN = re.compile(r"__version__\s*=\s*['\"]([^'\"]+)['\"]") PYPROJECT_PATTERN = re.compile(r'^version\s*=\s*"([^"]+)"$', re.MULTILINE) -# Pattern to match SocketDev/socket-basics@vX.X.X or @vX.X.X -ACTION_VERSION_PATTERN = re.compile(r'(SocketDev/socket-basics|socket-basics)@v\d+\.\d+\.\d+') +# Pattern to match SocketDev/socket-basics@X.X.X or @X.X.X (without v prefix) +ACTION_VERSION_PATTERN = re.compile(r'(SocketDev/socket-basics|socket-basics)@v?\d+\.\d+\.\d+') # Pattern to match docker build with optional version tag (handles both new and existing tags) DOCKER_BUILD_PATTERN = re.compile(r'docker build (?:--platform [^\s]+ )?-t ([^\s:]+)(?::\d+\.\d+\.\d+)?') # Pattern to match docker run commands with version tags @@ -117,8 +117,8 @@ def update_readme_versions(version: str): content = readme_file.read_text() original_content = content - # Update action version references (SocketDev/socket-basics@vX.X.X) - content = ACTION_VERSION_PATTERN.sub(rf'\1@v{version}', content) + # Update action version references (SocketDev/socket-basics@X.X.X without v prefix) + content = ACTION_VERSION_PATTERN.sub(rf'\1@{version}', content) # Update docker build commands to include version tag def docker_build_replacement(match): diff --git a/README.md b/README.md index 66a5573..5ed4e71 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v4 - name: Run Socket Basics - uses: SocketDev/socket-basics@v1.0.4 + uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_security_api_key: ${{ secrets.SOCKET_SECURITY_API_KEY }} @@ -106,7 +106,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **Dashboard-Configured (Enterprise):** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_security_api_key: ${{ secrets.SOCKET_SECURITY_API_KEY }} @@ -115,7 +115,7 @@ Configure scanning policies, notification channels, and rule sets for your entir **CLI-Configured:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -129,10 +129,10 @@ Configure scanning policies, notification channels, and rule sets for your entir ```bash # Build with version tag -docker build -t socketdev/socket-basics:1.0.4 . +docker build -t socketdev/socket-basics:1.0.9 . # Run scan -docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.4 \ +docker run --rm -v "$PWD:/workspace" socketdev/socket-basics:1.0.9 \ --workspace /workspace \ --python-sast-enabled \ --secret-scanning-enabled \ @@ -249,11 +249,6 @@ We welcome contributions! To add new features: 3. **Configuration:** Add entries to `socket_basics/connectors.yaml` or `socket_basics/notifications.yaml` 4. **Tests:** Add test cases to `app_tests/` -See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines. - -## 📝 License - -This project is licensed under the terms specified in the [LICENSE](LICENSE) file. --- diff --git a/action.yml b/action.yml index bf2c991..d7667a4 100644 --- a/action.yml +++ b/action.yml @@ -5,24 +5,391 @@ author: "Socket" runs: using: "docker" image: "Dockerfile" + env: + # Core GitHub variables (these are automatically available, but we explicitly pass GITHUB_TOKEN) + GITHUB_TOKEN: ${{ inputs.github_token }} + # Input mappings for all parameters + INPUT_ALL_LANGUAGES_ENABLED: ${{ inputs.all_languages_enabled }} + INPUT_ALL_RULES_ENABLED: ${{ inputs.all_rules_enabled }} + INPUT_CONTAINER_IMAGES_TO_SCAN: ${{ inputs.container_images }} + INPUT_CPP_DISABLED_RULES: ${{ inputs.cpp_disabled_rules }} + INPUT_CPP_ENABLED_RULES: ${{ inputs.cpp_enabled_rules }} + INPUT_CPP_SAST_ENABLED: ${{ inputs.cpp_sast_enabled }} + INPUT_CSHARP_DISABLED_RULES: ${{ inputs.csharp_disabled_rules }} + INPUT_CSHARP_ENABLED_RULES: ${{ inputs.csharp_enabled_rules }} + INPUT_CSHARP_SAST_ENABLED: ${{ inputs.csharp_sast_enabled }} + INPUT_C_DISABLED_RULES: ${{ inputs.c_disabled_rules }} + INPUT_C_ENABLED_RULES: ${{ inputs.c_enabled_rules }} + INPUT_C_SAST_ENABLED: ${{ inputs.c_sast_enabled }} + INPUT_DISABLE_ALL_SECRETS: ${{ inputs.disable_all_secrets }} + INPUT_DOCKERFILES: ${{ inputs.dockerfiles }} + INPUT_DOTNET_DISABLED_RULES: ${{ inputs.dotnet_disabled_rules }} + INPUT_DOTNET_ENABLED_RULES: ${{ inputs.dotnet_enabled_rules }} + INPUT_DOTNET_SAST_ENABLED: ${{ inputs.dotnet_sast_enabled }} + INPUT_ELIXIR_DISABLED_RULES: ${{ inputs.elixir_disabled_rules }} + INPUT_ELIXIR_ENABLED_RULES: ${{ inputs.elixir_enabled_rules }} + INPUT_ELIXIR_SAST_ENABLED: ${{ inputs.elixir_sast_enabled }} + INPUT_ERLANG_SAST_ENABLED: ${{ inputs.erlang_sast_enabled }} + INPUT_GITHUB_TOKEN: ${{ inputs.github_token }} + INPUT_GOLANG_SAST_ENABLED: ${{ inputs.golang_sast_enabled }} + INPUT_GO_DISABLED_RULES: ${{ inputs.go_disabled_rules }} + INPUT_GO_ENABLED_RULES: ${{ inputs.go_enabled_rules }} + INPUT_GO_SAST_ENABLED: ${{ inputs.go_sast_enabled }} + INPUT_JAVASCRIPT_DISABLED_RULES: ${{ inputs.javascript_disabled_rules }} + INPUT_JAVASCRIPT_ENABLED_RULES: ${{ inputs.javascript_enabled_rules }} + INPUT_JAVASCRIPT_SAST_ENABLED: ${{ inputs.javascript_sast_enabled }} + INPUT_JAVA_DISABLED_RULES: ${{ inputs.java_disabled_rules }} + INPUT_JAVA_ENABLED_RULES: ${{ inputs.java_enabled_rules }} + INPUT_JAVA_SAST_ENABLED: ${{ inputs.java_sast_enabled }} + INPUT_JIRA_API_TOKEN: ${{ inputs.jira_api_token }} + INPUT_JIRA_EMAIL: ${{ inputs.jira_email }} + INPUT_JIRA_PROJECT: ${{ inputs.project }} + INPUT_JIRA_URL: ${{ inputs.server }} + INPUT_KOTLIN_DISABLED_RULES: ${{ inputs.kotlin_disabled_rules }} + INPUT_KOTLIN_ENABLED_RULES: ${{ inputs.kotlin_enabled_rules }} + INPUT_KOTLIN_SAST_ENABLED: ${{ inputs.kotlin_sast_enabled }} + INPUT_MSTEAMS_WEBHOOK_URL: ${{ inputs.msteams_webhook_url }} + INPUT_MS_SENTINEL_KEY: ${{ inputs.ms_sentinel_key }} + INPUT_MS_SENTINEL_WORKSPACE_ID: ${{ inputs.ms_sentinel_workspace_id }} + INPUT_PHP_DISABLED_RULES: ${{ inputs.php_disabled_rules }} + INPUT_PHP_ENABLED_RULES: ${{ inputs.php_enabled_rules }} + INPUT_PHP_SAST_ENABLED: ${{ inputs.php_sast_enabled }} + INPUT_PYTHON_DISABLED_RULES: ${{ inputs.python_disabled_rules }} + INPUT_PYTHON_ENABLED_RULES: ${{ inputs.python_enabled_rules }} + INPUT_PYTHON_SAST_ENABLED: ${{ inputs.python_sast_enabled }} + INPUT_RUBY_DISABLED_RULES: ${{ inputs.ruby_disabled_rules }} + INPUT_RUBY_ENABLED_RULES: ${{ inputs.ruby_enabled_rules }} + INPUT_RUBY_SAST_ENABLED: ${{ inputs.ruby_sast_enabled }} + INPUT_RUST_DISABLED_RULES: ${{ inputs.rust_disabled_rules }} + INPUT_RUST_ENABLED_RULES: ${{ inputs.rust_enabled_rules }} + INPUT_RUST_SAST_ENABLED: ${{ inputs.rust_sast_enabled }} + INPUT_SCALA_DISABLED_RULES: ${{ inputs.scala_disabled_rules }} + INPUT_SCALA_ENABLED_RULES: ${{ inputs.scala_enabled_rules }} + INPUT_SCALA_SAST_ENABLED: ${{ inputs.scala_sast_enabled }} + INPUT_SECRET_SCANNING_ENABLED: ${{ inputs.secret_scanning_enabled }} + INPUT_SLACK_WEBHOOK_URL: ${{ inputs.slack_webhook_url }} + INPUT_SOCKET_ORG: ${{ inputs.socket_org }} + INPUT_SOCKET_SECURITY_API_KEY: ${{ inputs.socket_security_api_key }} + INPUT_SUMOLOGIC_ENDPOINT: ${{ inputs.sumologic_endpoint }} + INPUT_SWIFT_DISABLED_RULES: ${{ inputs.swift_disabled_rules }} + INPUT_SWIFT_ENABLED_RULES: ${{ inputs.swift_enabled_rules }} + INPUT_SWIFT_SAST_ENABLED: ${{ inputs.swift_sast_enabled }} + INPUT_TRIVY_DISABLED_RULES: ${{ inputs.trivy_disabled_rules }} + INPUT_TRIVY_IMAGE_SCANNING_DISABLED: ${{ inputs.trivy_image_scanning_disabled }} + INPUT_TRIVY_NOTIFICATION_METHOD: ${{ inputs.trivy_notification_method }} + INPUT_TRIVY_VULN_ENABLED: ${{ inputs.trivy_vuln_enabled }} + INPUT_TRUFFLEHOG_EXCLUDE_DIR: ${{ inputs.trufflehog_exclude_dir }} + INPUT_TRUFFLEHOG_NOTIFICATION_METHOD: ${{ inputs.notification_method }} + INPUT_TRUFFLEHOG_SHOW_UNVERIFIED: ${{ inputs.trufflehog_show_unverified }} + INPUT_WEBHOOK_URL: ${{ inputs.webhook_url }} + SOCKET_ADDITIONAL_PARAMS: ${{ inputs.socket_additional_params }} + SOCKET_TIER_1_ENABLED: ${{ inputs.socket_tier_1_enabled }} inputs: - # Socket Configuration socket_org: description: "Socket organization slug (required for Enterprise features)" required: false default: "" - socket_security_api_key: description: "Socket Security API key (required for Enterprise features and Dashboard configuration)" required: false default: "" - - # GitHub Integration github_token: description: "GitHub token for PR comments and API access" required: false default: "" + GITHUB_API_URL: + description: "Github Api Url" + required: false + default: "" + all_languages_enabled: + description: "Enable SAST for all supported languages" + required: false + default: "false" + all_rules_enabled: + description: "Run all bundled SAST rules regardless of language filters" + required: false + default: "false" + c_disabled_rules: + description: "Comma-separated list of C SAST rules to disable" + required: false + default: "" + c_enabled_rules: + description: "Comma-separated list of C SAST rules to enable (default: high-confidence rules)" + required: false + default: "c-buffer-overflow,c-format-string-vulnerability,c-command-injection,c-sql-injection,c-use-after-free,c-hardcoded-secrets,c-weak-crypto,c-ssl-issues" + c_sast_enabled: + description: "Enable C SAST scanning" + required: false + default: "false" + container_images: + description: "Comma-separated list of container images to scan (auto-enables image scanning)" + required: false + default: "" + cpp_disabled_rules: + description: "Comma-separated list of C++ SAST rules to disable" + required: false + default: "" + cpp_enabled_rules: + description: "Comma-separated list of C++ SAST rules to enable (default: high-confidence rules)" + required: false + default: "c-buffer-overflow,c-format-string-vulnerability,c-command-injection,c-sql-injection,c-use-after-free,c-hardcoded-secrets,c-weak-crypto,c-ssl-issues,cpp-unsafe-cast,cpp-memory-management" + cpp_sast_enabled: + description: "Enable C++ SAST scanning" + required: false + default: "false" + csharp_disabled_rules: + description: "Comma-separated list of C# SAST rules to disable" + required: false + default: "" + csharp_enabled_rules: + description: "Comma-separated list of C# SAST rules to enable (default: high-confidence rules)" + required: false + default: "dotnet-sql-injection,dotnet-command-injection,dotnet-code-injection,dotnet-unsafe-deserialization,dotnet-ldap-injection,dotnet-hardcoded-credentials,dotnet-ssl-bypass,dotnet-xxe-vulnerability,dotnet-xpath-injection" + csharp_sast_enabled: + description: "Enable C# SAST scanning" + required: false + default: "false" + disable_all_secrets: + description: "Disable all secret scanning features" + required: false + default: "false" + dockerfiles: + description: "Comma-separated list of Dockerfiles to scan (auto-enables Dockerfile scanning)" + required: false + default: "" + dotnet_disabled_rules: + description: "Comma-separated list of .NET SAST rules to disable" + required: false + default: "" + dotnet_enabled_rules: + description: "Comma-separated list of .NET SAST rules to enable (default: high-confidence rules)" + required: false + default: "dotnet-sql-injection,dotnet-command-injection,dotnet-code-injection,dotnet-unsafe-deserialization,dotnet-ldap-injection,dotnet-hardcoded-credentials,dotnet-ssl-bypass,dotnet-xxe-vulnerability,dotnet-xpath-injection" + dotnet_sast_enabled: + description: "Enable .NET SAST scanning" + required: false + default: "false" + elixir_disabled_rules: + description: "Comma-separated list of Elixir SAST rules to disable" + required: false + default: "" + elixir_enabled_rules: + description: "Comma-separated list of Elixir SAST rules to enable (default: high-confidence rules)" + required: false + default: "elixir-code-injection,elixir-sql-injection,elixir-command-injection,elixir-unsafe-deserialization,elixir-hardcoded-secrets,elixir-phoenix-ecto-injection" + elixir_sast_enabled: + description: "Enable Elixir SAST scanning" + required: false + default: "false" + erlang_sast_enabled: + description: "Enable Erlang SAST scanning" + required: false + default: "false" + go_disabled_rules: + description: "Comma-separated list of Go SAST rules to disable" + required: false + default: "" + go_enabled_rules: + description: "Comma-separated list of Go SAST rules to enable (default: high-confidence rules)" + required: false + default: "go-hardcoded-credentials,go-bind-all-interfaces,go-unsafe-usage,go-ssh-insecure-ignore-host-key,go-profiling-endpoint-exposed,go-decompression-bomb,go-sql-format-string" + go_sast_enabled: + description: "Enable Go SAST scanning" + required: false + default: "false" + golang_sast_enabled: + description: "Enable Golang SAST scanning" + required: false + default: "false" + java_disabled_rules: + description: "Comma-separated list of Java SAST rules to disable" + required: false + default: "" + java_enabled_rules: + description: "Comma-separated list of Java SAST rules to enable (default: high-confidence rules)" + required: false + default: "java-sql-injection,java-unsafe-deserialization,java-command-injection,java-ldap-injection,java-hardcoded-credentials,java-weak-crypto-md5,java-weak-crypto-sha1,java-xxe-vulnerability,java-ssl-bypass,java-weak-ssl-version,java-jndi-injection,java-el-injection" + java_sast_enabled: + description: "Enable Java SAST scanning" + required: false + default: "false" + javascript_disabled_rules: + description: "Comma-separated list of JavaScript/TypeScript SAST rules to disable" + required: false + default: "" + javascript_enabled_rules: + description: "Comma-separated list of JavaScript/TypeScript SAST rules to enable (default: high-confidence rules)" + required: false + default: "js-eval-usage,js-sql-injection,js-command-injection,js-prototype-pollution,js-xss-innerhtml,js-path-traversal,js-tls-reject-unauthorized-false,js-weak-crypto-md5" + javascript_sast_enabled: + description: "Enable JavaScript/TypeScript SAST scanning" + required: false + default: "false" + jira_api_token: + description: "Jira Api Token" + required: false + default: "" + jira_email: + description: "Jira Email" + required: false + default: "" + kotlin_disabled_rules: + description: "Comma-separated list of Kotlin SAST rules to disable" + required: false + default: "" + kotlin_enabled_rules: + description: "Comma-separated list of Kotlin SAST rules to enable (default: high-confidence rules)" + required: false + default: "kotlin-sql-injection,kotlin-command-injection,kotlin-code-injection,kotlin-unsafe-deserialization,kotlin-hardcoded-secrets,kotlin-ssl-bypass,kotlin-xxe-vulnerability,kotlin-ldap-injection" + kotlin_sast_enabled: + description: "Enable Kotlin SAST scanning" + required: false + default: "false" + ms_sentinel_key: + description: "Ms Sentinel Key" + required: false + default: "" + ms_sentinel_workspace_id: + description: "Ms Sentinel Workspace Id" + required: false + default: "" + msteams_webhook_url: + description: "MS Teams incoming webhook URL (also reads MSTEAMS_WEBHOOK_URL or INPUT_MSTEAMS_WEBHOOK_URL)" + required: false + default: "" + notification_method: + description: "Notification method for TruffleHog (e.g., console, slack)" + required: false + default: "" + php_disabled_rules: + description: "Comma-separated list of PHP SAST rules to disable" + required: false + default: "" + php_enabled_rules: + description: "Comma-separated list of PHP SAST rules to enable (default: high-confidence rules)" + required: false + default: "php-code-injection,php-sql-injection,php-command-injection,php-unsafe-deserialization,php-ldap-injection,php-file-inclusion,php-xxe-vulnerability,php-hardcoded-secrets,php-path-traversal" + php_sast_enabled: + description: "Enable PHP SAST scanning" + required: false + default: "false" + project: + description: "Project" + required: false + default: "" + python_disabled_rules: + description: "Comma-separated list of Python SAST rules to disable" + required: false + default: "" + python_enabled_rules: + description: "Comma-separated list of Python SAST rules to enable (default: high-confidence rules)" + required: false + default: "python-exec-used,python-bad-file-permissions,python-hardcoded-password-string,python-eval-usage,python-request-without-cert-validation,python-ssl-bad-version,python-subprocess-shell-true,python-start-process-with-shell,python-sql-injection-format,python-flask-debug-true,python-jinja2-autoescape-false" + python_sast_enabled: + description: "Enable Python SAST scanning" + required: false + default: "false" + ruby_disabled_rules: + description: "Comma-separated list of Ruby SAST rules to disable" + required: false + default: "" + ruby_enabled_rules: + description: "Comma-separated list of Ruby SAST rules to enable (default: high-confidence rules)" + required: false + default: "ruby-eval-injection,ruby-command-injection,ruby-sql-injection,ruby-unsafe-deserialization,ruby-hardcoded-secrets,ruby-ssl-verification-bypass,ruby-rails-find-by-sql-injection,ruby-rails-unsafe-constantize,ruby-xxe-vulnerability" + ruby_sast_enabled: + description: "Enable Ruby SAST scanning" + required: false + default: "false" + rust_disabled_rules: + description: "Comma-separated list of Rust SAST rules to disable" + required: false + default: "" + rust_enabled_rules: + description: "Comma-separated list of Rust SAST rules to enable (default: high-confidence rules)" + required: false + default: "rust-command-injection,rust-unsafe-deserialization,rust-sql-injection,rust-hardcoded-secrets,rust-insecure-tls,rust-buffer-overflow-potential" + rust_sast_enabled: + description: "Enable Rust SAST scanning" + required: false + default: "false" + scala_disabled_rules: + description: "Comma-separated list of Scala SAST rules to disable" + required: false + default: "" + scala_enabled_rules: + description: "Comma-separated list of Scala SAST rules to enable (default: high-confidence rules)" + required: false + default: "scala-sql-injection,scala-code-injection,scala-command-injection,scala-unsafe-deserialization,scala-hardcoded-secrets,scala-ssl-bypass,scala-slick-sql-injection" + scala_sast_enabled: + description: "Enable Scala SAST scanning" + required: false + default: "false" + secret_scanning_enabled: + description: "Enable secret scanning" + required: false + default: "false" + server: + description: "Server" + required: false + default: "" + slack_webhook_url: + description: "Slack webhook URL (also reads SLACK_WEBHOOK_URL or INPUT_SLACK_WEBHOOK_URL)" + required: false + default: "" + socket_additional_params: + description: "Additional CLI params for 'socket scan reach' (comma or space separated). Also reads SOCKET_ADDITIONAL_PARAMS" + required: false + default: "" + socket_tier_1_enabled: + description: "Enable Socket Tier 1 reachability analysis" + required: false + default: "false" + sumologic_endpoint: + description: "Sumologic Endpoint" + required: false + default: "" + swift_disabled_rules: + description: "Comma-separated list of Swift SAST rules to disable" + required: false + default: "" + swift_enabled_rules: + description: "Comma-separated list of Swift SAST rules to enable (default: high-confidence rules)" + required: false + default: "swift-sql-injection,swift-command-injection,swift-unsafe-deserialization,swift-hardcoded-secrets,swift-ssl-bypass,swift-insecure-urlsession,swift-certificate-pinning-bypass" + swift_sast_enabled: + description: "Enable Swift SAST scanning" + required: false + default: "false" + trivy_disabled_rules: + description: "Comma-separated list of Trivy rules to disable" + required: false + default: "" + trivy_image_scanning_disabled: + description: "Disable Trivy image scanning" + required: false + default: "false" + trivy_notification_method: + description: "Notification method for Trivy (e.g., console, slack)" + required: false + default: "" + trivy_vuln_enabled: + description: "Enable Trivy vulnerability scanning for all supported language ecosystems" + required: false + default: "false" + trufflehog_exclude_dir: + description: "Comma-separated list of directories to exclude from secret scanning" + required: false + default: "" + trufflehog_show_unverified: + description: "Show unverified secrets in TruffleHog results" + required: false + default: "false" + webhook_url: + description: "Generic webhook URL for WebhookNotifier" + required: false + default: "" branding: icon: "shield" diff --git a/docs/github-action.md b/docs/github-action.md index 617c23d..8d2bcd4 100644 --- a/docs/github-action.md +++ b/docs/github-action.md @@ -29,12 +29,19 @@ on: jobs: security-scan: + permissions: + issues: write + contents: read + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run Socket Basics - uses: SocketDev/socket-basics@v1.0.4 + uses: SocketDev/socket-basics@1.0.9 + env: + # Optional: Explicitly set PR number for guaranteed PR comments + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -45,9 +52,23 @@ This will: - ✅ Run Python SAST on all `.py` files - ✅ Scan for leaked secrets - ✅ Post results as a PR comment +- ✅ Post results as a PR comment ## Basic Configuration +### Required Permissions + +Socket Basics requires the following permissions to post PR comments and create issues: + +```yaml +permissions: + issues: write # Create and update issues for findings + contents: read # Read repository contents + pull-requests: write # Post comments on pull requests +``` + +Include these in your workflow's `jobs..permissions` section. + ### Required Inputs **`github_token`** (required) @@ -58,7 +79,7 @@ This will: **SAST (Static Analysis):** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Enable SAST for specific languages @@ -72,7 +93,7 @@ This will: **Secret Scanning:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} secret_scanning_enabled: 'true' @@ -84,7 +105,7 @@ This will: **Container Scanning:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Scan Docker images (auto-enables container scanning) @@ -95,7 +116,7 @@ This will: **Socket Tier 1 Reachability:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_tier_1_enabled: 'true' @@ -104,7 +125,7 @@ This will: ### Output Configuration ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} python_sast_enabled: 'true' @@ -134,7 +155,10 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev **Enable in workflow:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 + env: + # Optional: Explicitly set PR number for guaranteed PR comments + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: github_token: ${{ secrets.GITHUB_TOKEN }} # Dashboard configuration (Enterprise required) @@ -142,6 +166,16 @@ Configure Socket Basics centrally from the [Socket Dashboard](https://socket.dev socket_security_api_key: ${{ secrets.SOCKET_SECURITY_API_KEY }} ``` +> **Note:** You can also pass credentials using environment variables instead of the `with:` section: +> ```yaml +> - uses: SocketDev/socket-basics@1.0.9 +> env: +> SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} +> with: +> github_token: ${{ secrets.GITHUB_TOKEN }} +> ``` +> Both approaches work identically. Use whichever fits your workflow style. + Your workflow will automatically use the settings configured in the dashboard. ![Socket Basics Section Configuration](screenshots/socket_basics_section_config.png) @@ -152,7 +186,7 @@ All notification integrations require Socket Enterprise. **Slack Notifications:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -164,7 +198,7 @@ All notification integrations require Socket Enterprise. **Jira Issue Creation:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -179,7 +213,7 @@ All notification integrations require Socket Enterprise. **Microsoft Teams:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -191,7 +225,7 @@ All notification integrations require Socket Enterprise. **Generic Webhook:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -203,7 +237,7 @@ All notification integrations require Socket Enterprise. **SIEM Integration:** ```yaml -- uses: SocketDev/socket-basics@v1.0.4 +- uses: SocketDev/socket-basics@1.0.9 with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -229,12 +263,19 @@ on: jobs: security-scan: + permissions: + issues: write + contents: read + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run Socket Basics - uses: SocketDev/socket-basics@v1.0.4 + uses: SocketDev/socket-basics@1.0.9 + env: + # Optional: Explicitly set PR number for guaranteed PR comments + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -269,12 +310,19 @@ on: jobs: security-audit: + permissions: + issues: write + contents: read + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run Full Security Scan - uses: SocketDev/socket-basics@v1.0.4 + uses: SocketDev/socket-basics@1.0.9 + env: + # Optional: Explicitly set PR number for guaranteed PR comments + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: github_token: ${{ secrets.GITHUB_TOKEN }} socket_org: ${{ secrets.SOCKET_ORG }} @@ -312,15 +360,22 @@ on: jobs: container-scan: + permissions: + issues: write + contents: read + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build Docker Image - run: docker build -t myapp:1.0.4:${{ github.sha }} . + run: docker build -t myapp:1.0.9:${{ github.sha }} . - name: Scan Container - uses: SocketDev/socket-basics@v1.0.4 + uses: SocketDev/socket-basics@1.0.9 + env: + # Optional: Explicitly set PR number for guaranteed PR comments + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: github_token: ${{ secrets.GITHUB_TOKEN }} @@ -340,12 +395,19 @@ on: [pull_request] jobs: security-scan: + permissions: + issues: write + contents: read + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run Socket Basics - uses: SocketDev/socket-basics@v1.0.4 + uses: SocketDev/socket-basics@1.0.9 + env: + # Optional: Explicitly set PR number for guaranteed PR comments + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} with: github_token: ${{ secrets.GITHUB_TOKEN }} @@ -436,7 +498,7 @@ env: ```yaml steps: - uses: actions/checkout@v4 # Must be first - - uses: SocketDev/socket-basics@v1.0.4 + - uses: SocketDev/socket-basics@1.0.9 ``` ### PR Comments Not Appearing diff --git a/docs/local-install-docker.md b/docs/local-install-docker.md index d4cce5c..f8823f4 100644 --- a/docs/local-install-docker.md +++ b/docs/local-install-docker.md @@ -17,7 +17,7 @@ Run Socket Basics locally using Docker without installing any security tools on # 1. Clone and build git clone https://github.com/SocketDev/socket-basics.git cd socket-basics -docker build -t socket-basics:1.0.4 . +docker build -t socket-basics:1.0.9 . # 2. Create .env file with your credentials cat > .env << 'EOF' @@ -29,7 +29,7 @@ EOF docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --python \ --secrets \ @@ -46,10 +46,10 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build with version tag -docker build -t socket-basics:1.0.4 . +docker build -t socket-basics:1.0.9 . # Or build with latest tag -docker build -t socket-basics:1.0.4:latest . +docker build -t socket-basics:1.0.9:latest . # Verify the build docker images | grep socket-basics @@ -59,21 +59,21 @@ docker images | grep socket-basics ```bash # Use your own image name -docker build -t myorg/security-scanner:1.0.4 . +docker build -t myorg/security-scanner:1.0.9 . # Build for specific platform (e.g., for M1/M2 Macs) -docker build --platform linux/amd64 -t socket-basics:1.0.4 . +docker build --platform linux/amd64 -t socket-basics:1.0.9 . ``` ### Verify Installation ```bash # Check that all tools are available in the container -docker run --rm socket-basics:1.0.4 socket-basics --version -docker run --rm socket-basics:1.0.4 socket --version -docker run --rm socket-basics:1.0.4 trivy --version -docker run --rm socket-basics:1.0.4 semgrep --version -docker run --rm socket-basics:1.0.4 trufflehog --version +docker run --rm socket-basics:1.0.9 socket-basics --version +docker run --rm socket-basics:1.0.9 socket --version +docker run --rm socket-basics:1.0.9 trivy --version +docker run --rm socket-basics:1.0.9 semgrep --version +docker run --rm socket-basics:1.0.9 trufflehog --version ``` ## Running Scans @@ -86,7 +86,7 @@ Mount your project directory into the container: # Scan current directory docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --python \ --secrets \ @@ -103,7 +103,7 @@ docker run --rm \ # Scan a specific project directory docker run --rm \ -v "/path/to/your/project:/workspace" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --javascript \ --secrets @@ -114,7 +114,7 @@ docker run --rm \ ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -162,7 +162,7 @@ VERBOSE=false docker run --rm \ -v "$PWD:/workspace" \ --env-file .env \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --python \ --secrets @@ -177,7 +177,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=scrt_your_api_key" \ -e "SOCKET_ORG=your-org-slug" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --python \ --secrets \ @@ -199,7 +199,7 @@ docker run --rm \ --env-file .env.socket \ --env-file .env.notifiers \ --env-file .env.scanning \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --all-languages ``` @@ -218,7 +218,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -e "SOCKET_SECURITY_API_KEY=$SOCKET_SECURITY_API_KEY" \ -e "SOCKET_ORG=$SOCKET_ORG" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --python ``` @@ -234,7 +234,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "/var/run/docker.sock:/var/run/docker.sock" \ --env-file .env \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --images "nginx:latest,redis:7" \ --console-tabular-enabled @@ -255,7 +255,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/scan-results:/results" \ --env-file .env \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --python \ --secrets \ @@ -272,7 +272,7 @@ docker run --rm -it \ -v "$PWD:/workspace" \ --env-file .env \ --entrypoint /bin/bash \ - socket-basics:1.0.4 + socket-basics:1.0.9 # Inside container, run commands manually: # cd /workspace @@ -301,7 +301,7 @@ docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/socket-config.json:/config.json" \ --env-file .env \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --config /config.json ``` @@ -325,7 +325,7 @@ for PROJECT in "${PROJECTS[@]}"; do docker run --rm \ -v "$PROJECT:/workspace" \ --env-file .env \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --all-languages \ --secrets \ @@ -345,7 +345,7 @@ pipeline { stage('Security Scan') { steps { script { - docker.image('socket-basics:1.0.4').inside( + docker.image('socket-basics:1.0.9').inside( "-v ${WORKSPACE}:/workspace --env-file .env" ) { sh ''' @@ -367,7 +367,7 @@ pipeline { ```yaml security-scan: - image: socket-basics:1.0.4 + image: socket-basics:1.0.9 stage: test script: - socket-basics @@ -393,7 +393,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --user "$(id -u):$(id -g)" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace ``` @@ -412,14 +412,14 @@ security-scan: ```bash docker run --rm \ -v "$(pwd):/workspace" \ # Use $(pwd) instead of $PWD - socket-basics:1.0.4 + socket-basics:1.0.9 ``` 2. Verify mount: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ ls -la /workspace ``` @@ -449,7 +449,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ --env-file "$(pwd)/.env" \ - socket-basics:1.0.4 + socket-basics:1.0.9 ``` ### Docker Socket Permission Denied @@ -497,7 +497,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --python \ --secrets \ @@ -518,7 +518,7 @@ security-scan: ```bash docker run --rm \ -v "$PWD:/workspace" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --output /workspace/results.json # Save to mounted directory ``` @@ -529,7 +529,7 @@ security-scan: docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/results:/results" \ - socket-basics:1.0.4 \ + socket-basics:1.0.9 \ --workspace /workspace \ --output /results/scan.json ``` @@ -540,14 +540,14 @@ Add these to your `~/.bashrc` or `~/.zshrc` for quick access: ```bash # Socket Basics Docker aliases -alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.4 --workspace /workspace' +alias sb-docker='docker run --rm -v "$PWD:/workspace" --env-file .env socket-basics:1.0.9 --workspace /workspace' alias sb-quick='sb-docker --secrets --console-tabular-enabled' alias sb-python='sb-docker --python --secrets --console-tabular-enabled' alias sb-js='sb-docker --javascript --secrets --console-tabular-enabled' alias sb-all='sb-docker --all-languages --secrets --socket-tier1 --console-tabular-enabled' # Rebuild image -alias sb-build='docker build -t socket-basics:1.0.4 .' +alias sb-build='docker build -t socket-basics:1.0.9 .' ``` Usage: @@ -583,7 +583,7 @@ set -e # Configuration PROJECT_DIR="$(pwd)" RESULTS_DIR="./scan-results" -IMAGE_NAME="socket-basics:1.0.4" +IMAGE_NAME="socket-basics:1.0.9" ENV_FILE=".env" # Create results directory diff --git a/docs/pre-commit-hook.md b/docs/pre-commit-hook.md index 0bb79e6..c9869b0 100644 --- a/docs/pre-commit-hook.md +++ b/docs/pre-commit-hook.md @@ -39,7 +39,7 @@ git clone https://github.com/SocketDev/socket-basics.git cd socket-basics # Build the Docker image with version tag -docker build -t socket-basics:1.0.4 . +docker build -t socket-basics:1.0.9 . ``` **2. Create pre-commit hook:** diff --git a/pyproject.toml b/pyproject.toml index f45dd34..14c0e48 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket_basics" -version = "1.0.4" +version = "1.0.9" description = "Socket Basics with integrated SAST, secret scanning, and container analysis" readme = "README.md" requires-python = ">=3.10" diff --git a/socket_basics/core/config.py b/socket_basics/core/config.py index e5e7d26..0a7465a 100644 --- a/socket_basics/core/config.py +++ b/socket_basics/core/config.py @@ -570,30 +570,39 @@ def load_socket_basics_config() -> Dict[str, Any] | None: logger.debug(" load_socket_basics_config() called") # Check if Socket API integration is available + # Support both direct env vars and GitHub Actions INPUT_ prefixed vars api_key = ( os.environ.get('SOCKET_SECURITY_API_KEY') or os.environ.get('SOCKET_SECURITY_API_TOKEN') + or os.environ.get('INPUT_SOCKET_SECURITY_API_KEY') ) logger.debug(f" API key check - SOCKET_SECURITY_API_KEY set: {bool(os.environ.get('SOCKET_SECURITY_API_KEY'))}") logger.debug(f" API key check - SOCKET_SECURITY_API_TOKEN set: {bool(os.environ.get('SOCKET_SECURITY_API_TOKEN'))}") + logger.debug(f" API key check - INPUT_SOCKET_SECURITY_API_KEY set: {bool(os.environ.get('INPUT_SOCKET_SECURITY_API_KEY'))}") logger.debug(f" Final api_key available: {bool(api_key)}") if not api_key: - logger.debug(" Socket API key not available, returning free plan config") + logger.info("Socket API key not detected - running in free plan mode (limited features)") + logger.debug("Checked: SOCKET_SECURITY_API_KEY, SOCKET_SECURITY_API_TOKEN, INPUT_SOCKET_SECURITY_API_KEY") return { 'socket_plan': 'free', 'socket_has_enterprise': False, 'available_notifiers': ['console_tabular', 'console_json'] } + logger.info("Socket API key detected - attempting to load dashboard configuration") + + # Support both direct env vars and GitHub Actions INPUT_ prefixed vars org_slug = ( os.environ.get('SOCKET_ORG_SLUG') or os.environ.get('SOCKET_ORG') + or os.environ.get('INPUT_SOCKET_ORG') ) logger.debug(f" SOCKET_ORG_SLUG: {os.environ.get('SOCKET_ORG_SLUG', 'not set')}") logger.debug(f" SOCKET_ORG: {os.environ.get('SOCKET_ORG', 'not set')}") + logger.debug(f" INPUT_SOCKET_ORG: {os.environ.get('INPUT_SOCKET_ORG', 'not set')}") logger.debug(f" org_slug from env: {org_slug or 'not set - will auto-discover'}") try: @@ -702,8 +711,19 @@ def load_socket_basics_config() -> Dict[str, Any] | None: def load_explicit_env_config() -> Dict[str, Any]: """Load only explicitly set environment variables (not defaults)""" + logger = logging.getLogger(__name__) config = {} + # Log which API key sources are available for debugging + api_key_sources = { + 'SOCKET_SECURITY_API_KEY': bool(os.environ.get('SOCKET_SECURITY_API_KEY')), + 'SOCKET_SECURITY_API_TOKEN': bool(os.environ.get('SOCKET_SECURITY_API_TOKEN')), + 'INPUT_SOCKET_SECURITY_API_KEY': bool(os.environ.get('INPUT_SOCKET_SECURITY_API_KEY')), + } + found_sources = [k for k, v in api_key_sources.items() if v] + if found_sources: + logger.debug(f"API key sources detected: {', '.join(found_sources)}") + # Core settings - only if explicitly set if 'GITHUB_WORKSPACE' in os.environ: config['workspace'] = os.environ['GITHUB_WORKSPACE'] @@ -926,11 +946,10 @@ def normalize_api_config(api_config: Dict[str, Any]) -> Dict[str, Any]: def merge_json_and_env_config(json_config: Dict[str, Any] | None = None) -> Dict[str, Any]: """Merge JSON configuration with environment variables - Priority order: - 1. Explicitly set environment variables (highest priority) - 2. JSON config (if provided) - 3. Socket Basics API config (if no JSON config and API available) - 4. Environment defaults (lowest priority) + Priority order (highest to lowest): + 1. CLI options (handled separately via argparse, highest priority) + 2. Socket Basics API config / JSON config (dashboard settings) + 3. Environment variables from action.yml (lowest priority - defaults) Args: json_config: Optional dictionary from JSON config file @@ -938,10 +957,11 @@ def merge_json_and_env_config(json_config: Dict[str, Any] | None = None) -> Dict Returns: Merged configuration dictionary """ - # Start with environment defaults + # Start with environment defaults (lowest priority) config = load_config_from_env() # Override with Socket Basics API config if no explicit JSON config provided + # API config takes precedence over environment defaults if not json_config: logger = logging.getLogger(__name__) logger.debug(" No JSON config provided, attempting to load Socket Basics API config") @@ -951,25 +971,20 @@ def merge_json_and_env_config(json_config: Dict[str, Any] | None = None) -> Dict # Normalize camelCase API keys to snake_case internal format normalized_config = normalize_api_config(socket_basics_config) config.update(normalized_config) - logging.getLogger(__name__).info("Loaded Socket Basics configuration from API") + logging.getLogger(__name__).info("Loaded Socket Basics API configuration (overrides environment defaults)") else: logger.debug(" No Socket Basics API config loaded") # Override with explicit JSON config if provided + # JSON config also takes precedence over environment defaults if json_config: # Also normalize JSON config in case it comes from API normalized_json = normalize_api_config(json_config) config.update(normalized_json) + logging.getLogger(__name__).info("Loaded JSON configuration (overrides environment defaults)") - # Finally, override with explicitly set environment variables (highest priority) - explicit_env = load_explicit_env_config() - config.update(explicit_env) - - logger = logging.getLogger(__name__) - if json_config: - logger.info("Merged JSON configuration with environment variables (explicit env takes precedence)") - elif socket_basics_config: - logger.info("Merged Socket Basics API configuration with environment variables (explicit env takes precedence)") + # Note: CLI arguments are handled separately and take highest priority + # They override the config object after this merge completes return config diff --git a/socket_basics/core/notification/github_pr_notifier.py b/socket_basics/core/notification/github_pr_notifier.py index 94e0120..524b4e9 100644 --- a/socket_basics/core/notification/github_pr_notifier.py +++ b/socket_basics/core/notification/github_pr_notifier.py @@ -156,17 +156,29 @@ def _get_pr_number(self) -> Optional[int]: # Try environment variables first pr_env = get_github_pr_number() if pr_env and pr_env.isdigit(): + logger.info(f"GithubPRNotifier: Using PR number from environment: {pr_env}") return int(pr_env) + logger.debug(f"GithubPRNotifier: No PR number in environment (GITHUB_PR_NUMBER: {pr_env or 'not set'})") + # Try to find via API - return self._find_pr_for_branch() + pr_number = self._find_pr_for_branch() + if pr_number: + logger.info(f"GithubPRNotifier: Found PR number via API: {pr_number}") + else: + logger.debug("GithubPRNotifier: Could not find PR number via API") + + return pr_number def _find_pr_for_branch(self) -> Optional[int]: """Find PR number for the given branch using API.""" owner_repo = self.repository branch = self.config.get('branch') + logger.debug(f"GithubPRNotifier: Searching for PR - repository: {owner_repo}, branch: {branch}") + if not self.repository or not branch: + logger.debug(f"GithubPRNotifier: Missing required info - repository: {bool(self.repository)}, branch: {bool(branch)}") return None try: @@ -179,11 +191,18 @@ def _find_pr_for_branch(self) -> Optional[int]: url = f"{self.api_base}/repos/{self.repository}/pulls" params = {'head': f"{self.repository.split('/')[0]}:{branch}", 'state': 'open'} + logger.debug(f"GithubPRNotifier: API request to {url} with params: {params}") + resp = requests.get(url, headers=headers, params=params, timeout=10) if resp.status_code == 200: prs = resp.json() if prs: + logger.debug(f"GithubPRNotifier: Found {len(prs)} open PR(s) for branch {branch}") return prs[0]['number'] + else: + logger.debug(f"GithubPRNotifier: No open PRs found for branch {branch}") + else: + logger.warning(f"GithubPRNotifier: API request failed with status {resp.status_code}") except Exception as e: logger.debug('GithubPRNotifier: failed to find PR for branch %s: %s', branch, e) diff --git a/socket_basics/core/notification/manager.py b/socket_basics/core/notification/manager.py index 27a1a44..095855c 100644 --- a/socket_basics/core/notification/manager.py +++ b/socket_basics/core/notification/manager.py @@ -136,8 +136,12 @@ def load_from_config(self) -> None: enabled = True if github_token: enable_cause = 'env:GITHUB_TOKEN or INPUT_GITHUB_TOKEN' + logger.info("GitHub PR notifier will be enabled - token detected") else: enable_cause = 'app_config:github_token' + logger.info("GitHub PR notifier will be enabled - token in config") + else: + logger.debug("GitHub PR notifier will NOT be enabled - no GITHUB_TOKEN found") except Exception: pass diff --git a/socket_basics/version.py b/socket_basics/version.py index 92192ee..39e0411 100644 --- a/socket_basics/version.py +++ b/socket_basics/version.py @@ -1 +1 @@ -__version__ = "1.0.4" +__version__ = "1.0.9"