diff --git a/.github/workflows/issues-jira.yml b/.github/workflows/issues-jira.yml new file mode 100644 index 0000000..7bf0469 --- /dev/null +++ b/.github/workflows/issues-jira.yml @@ -0,0 +1,31 @@ +name: Create Jira Ticket for Github Issue + +on: + issues: + types: [opened] + +jobs: + issue-jira: + runs-on: ubuntu-latest + steps: + + - name: Login to Jira + uses: atlassian/gajira-login@master + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + - name: Create Jira Issue + id: create_jira + uses: atlassian/gajira-create@master + with: + project: ${{ secrets.JIRA_PROJECT }} + issuetype: ${{ secrets.JIRA_ISSUE_TYPE }} + summary: Github | Issue | ${{ github.event.repository.name }} | ${{ github.event.issue.title }} + description: | + *GitHub Issue:* ${{ github.event.issue.html_url }} + + *Description:* + ${{ github.event.issue.body }} + fields: "${{ secrets.ISSUES_JIRA_FIELDS }}" \ No newline at end of file diff --git a/.github/workflows/jira.yml b/.github/workflows/jira.yml deleted file mode 100644 index caa4bbd..0000000 --- a/.github/workflows/jira.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Create JIRA ISSUE -on: - pull_request: - types: [opened] -jobs: - security-jira: - if: ${{ github.actor == 'dependabot[bot]' || github.actor == 'snyk-bot' || contains(github.event.pull_request.head.ref, 'snyk-fix-') || contains(github.event.pull_request.head.ref, 'snyk-upgrade-')}} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Login into JIRA - uses: atlassian/gajira-login@master - env: - JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} - JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} - JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} - - name: Create a JIRA Issue - id: create - uses: atlassian/gajira-create@master - with: - project: ${{ secrets.JIRA_PROJECT }} - issuetype: ${{ secrets.JIRA_ISSUE_TYPE }} - summary: | - ${{ github.event.pull_request.title }} - description: | - PR: ${{ github.event.pull_request.html_url }} - - fields: "${{ secrets.JIRA_FIELDS }}" - - name: Transition issue - uses: atlassian/gajira-transition@v3 - with: - issue: ${{ steps.create.outputs.issue }} - transition: ${{ secrets.JIRA_TRANSITION }} diff --git a/.github/workflows/policy-scan.yml b/.github/workflows/policy-scan.yml new file mode 100644 index 0000000..ff25923 --- /dev/null +++ b/.github/workflows/policy-scan.yml @@ -0,0 +1,46 @@ +name: Checks the security policy and configurations +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + security-policy: + if: github.event.repository.visibility == 'public' + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@master + - name: Checks for SECURITY.md policy file + run: | + if ! [[ -f "SECURITY.md" || -f ".github/SECURITY.md" ]]; then exit 1; fi + security-license: + if: github.event.repository.visibility == 'public' + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@master + - name: Checks for License file + run: | + expected_license_files=("LICENSE" "LICENSE.txt" "LICENSE.md" "License.txt") + license_file_found=false + current_year=$(date +"%Y") + + for license_file in "${expected_license_files[@]}"; do + if [ -f "$license_file" ]; then + license_file_found=true + # check the license file for the current year, if not exists, exit with error + if ! grep -q "$current_year" "$license_file"; then + echo "License file $license_file does not contain the current year." + exit 2 + fi + break + fi + done + + if [ "$license_file_found" = false ]; then + echo "No license file found. Please add a license file to the repository." + exit 1 + fi \ No newline at end of file diff --git a/.github/workflows/sast-scan.yml b/.github/workflows/sast-scan.yml deleted file mode 100644 index 3b9521a..0000000 --- a/.github/workflows/sast-scan.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: SAST Scan -on: - pull_request: - types: [opened, synchronize, reopened] -jobs: - security-sast: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Semgrep Scan - run: docker run -v /var/run/docker.sock:/var/run/docker.sock -v "${PWD}:/src" returntocorp/semgrep semgrep scan --config auto \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f6785b7..c423f28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ ## CHANGELOG -## Version 0.8.0 +## Version 0.8.2 +### Date: 12th-January-2026 + ### Improved error messages + - + +------------------------------------------------ + +## Version 0.8.1 ### Date: 05th-January-2026 ### Security Bug - Fixed snyk security issues and updated license year diff --git a/CODEOWNERS b/CODEOWNERS index 0773923..0496bc6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1,11 @@ -* @contentstack/security-admin \ No newline at end of file +* @contentstack/devex-pr-reviewers + +.github/workflows/sca-scan.yml @contentstack/security-admin + +.github/workflows/codeql-anaylsis.yml @contentstack/security-admin + +**/.snyk @contentstack/security-admin + +.github/workflows/policy-scan.yml @contentstack/security-admin + +.github/workflows/issues-jira.yml @contentstack/security-admin diff --git a/Gemfile.lock b/Gemfile.lock index 85b34a3..583aac9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,6 +68,7 @@ GEM simplecov_json_formatter (0.1.4) tzinfo (2.0.6) concurrent-ruby (~> 1.0) + uri (1.1.1) webmock (3.11.3) addressable (>= 2.3.6) crack (>= 0.3.2) @@ -76,6 +77,7 @@ GEM PLATFORMS arm64-darwin-22 + arm64-darwin-24 DEPENDENCIES contentstack! diff --git a/lib/contentstack/api.rb b/lib/contentstack/api.rb index f68fa5e..88f48b3 100644 --- a/lib/contentstack/api.rb +++ b/lib/contentstack/api.rb @@ -82,7 +82,7 @@ def self.fetch_retry(path, query=nil, count=0) sleep(retryDelay_in_seconds.to_i) #sleep method requires time in seconds as parameter response = fetch_retry(path, query, (count + 1)) else - raise Contentstack::Error.new(response) #Retry Limit exceeded + raise Contentstack::Error.new(Contentstack::ErrorMessages.request_failed(response)) #Retry Limit exceeded end else to_render_content(response) @@ -125,7 +125,7 @@ def self.send_request(path, q=nil) error_response = JSON.parse(response.string) error_status = {"status_code" => response.status[0], "status_message" => response.status[1]} error = error_response.merge(error_status) - raise Contentstack::Error.new(error.to_s) + raise Contentstack::Error.new(Contentstack::ErrorMessages.request_error(error)) end end @@ -165,7 +165,7 @@ def self.send_preview_request(path, q=nil) error_response = JSON.parse(response.string) error_status = {"status_code" => response.status[0], "status_message" => response.status[1]} error = error_response.merge(error_status) - raise Contentstack::Error.new(error.to_s) + raise Contentstack::Error.new(Contentstack::ErrorMessages.request_error(error)) end end diff --git a/lib/contentstack/client.rb b/lib/contentstack/client.rb index e66d5de..7d9a0cd 100644 --- a/lib/contentstack/client.rb +++ b/lib/contentstack/client.rb @@ -10,12 +10,12 @@ class Client attr_reader :region, :host # Initialize "Contentstack" Client instance def initialize(api_key, delivery_token, environment, options={}) - raise Contentstack::Error.new("Api Key is not valid") if api_key.class != String - raise Contentstack::Error.new("Api Key Field Should not be Empty") if api_key.empty? - raise Contentstack::Error.new("Delivery Token is not valid") if delivery_token.class != String - raise Contentstack::Error.new("Delivery Token Field Should not be Empty") if delivery_token.empty? - raise Contentstack::Error.new("Envirnoment Field is not valid") if environment.class != String - raise Contentstack::Error.new("Envirnoment Field Should not be Empty") if environment.empty? + raise Contentstack::Error.new(Contentstack::ErrorMessages::API_KEY_INVALID) if api_key.class != String + raise Contentstack::Error.new(Contentstack::ErrorMessages::API_KEY_REQUIRED) if api_key.empty? + raise Contentstack::Error.new(Contentstack::ErrorMessages::DELIVERY_TOKEN_INVALID) if delivery_token.class != String + raise Contentstack::Error.new(Contentstack::ErrorMessages::DELIVERY_TOKEN_REQUIRED) if delivery_token.empty? + raise Contentstack::Error.new(Contentstack::ErrorMessages::ENVIRONMENT_INVALID) if environment.class != String + raise Contentstack::Error.new(Contentstack::ErrorMessages::ENVIRONMENT_REQUIRED) if environment.empty? @region = options[:region].nil? ? Contentstack::Region::US : options[:region] # @host = options[:host].nil? ? get_default_region_hosts(@region) : options[:host] #removed for not supporting custom host with regions @host = get_host_by_region(@region, options) # Added new method for custom host support with different regions @@ -32,8 +32,8 @@ def initialize(api_key, delivery_token, environment, options={}) "retryLimit"=> @retryLimit, "errorRetry" => @errorRetry } - raise Contentstack::Error.new("Proxy URL Should not be Empty") if @proxy_details.present? && @proxy_details[:url].empty? - raise Contentstack::Error.new("Proxy Port Should not be Empty") if @proxy_details.present? && @proxy_details[:port].empty? + raise Contentstack::Error.new(Contentstack::ErrorMessages::PROXY_URL_REQUIRED) if @proxy_details.present? && @proxy_details[:url].empty? + raise Contentstack::Error.new(Contentstack::ErrorMessages::PROXY_PORT_REQUIRED) if @proxy_details.present? && @proxy_details[:port].empty? API.init_api(api_key, delivery_token, environment, @host, @branch, @live_preview, @proxy_details, retry_options) end diff --git a/lib/contentstack/error.rb b/lib/contentstack/error.rb index 8a68926..288542a 100644 --- a/lib/contentstack/error.rb +++ b/lib/contentstack/error.rb @@ -1,4 +1,24 @@ module Contentstack + # Centralized error messages for the SDK + module ErrorMessages + API_KEY_INVALID = "API Key is invalid. Provide a valid API Key and try again." + API_KEY_REQUIRED = "API Key is required. Provide a valid API Key and try again." + DELIVERY_TOKEN_INVALID = "Delivery Token is invalid. Provide a valid Delivery Token and try again." + DELIVERY_TOKEN_REQUIRED = "Delivery Token is required. Provide a valid Delivery Token and try again." + ENVIRONMENT_INVALID = "Environment is invalid. Provide a valid Environment and try again." + ENVIRONMENT_REQUIRED = "Environment is required. Provide a valid Environment and try again." + PROXY_URL_REQUIRED = "Proxy URL is required. Provide a valid Proxy URL and try again." + PROXY_PORT_REQUIRED = "Proxy Port is required. Provide a valid Proxy Port and try again." + + def self.request_failed(response) + "The request could not be completed due to #{response}. Review the details and try again." + end + + def self.request_error(error) + "The request encountered an issue due to #{error}. Review the details and try again." + end + end + class Error < StandardError def initialize(msg="Something Went Wrong.") super diff --git a/lib/contentstack/version.rb b/lib/contentstack/version.rb index 33ee66d..bd4bbe0 100644 --- a/lib/contentstack/version.rb +++ b/lib/contentstack/version.rb @@ -1,3 +1,3 @@ module Contentstack - VERSION = "0.8.1" + VERSION = "0.8.2" end