From 35730ca936af7c749e54c345dcbeca168414a06f Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 06:50:17 -0700 Subject: [PATCH 01/17] tests: add a unit test and setup CI workflow --- .github/workflows/test.yml | 30 ++++++++++++++++++++++++++++++ tests/.gitkeep | 0 tests/test_vault.py | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 .github/workflows/test.yml delete mode 100644 tests/.gitkeep create mode 100644 tests/test_vault.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..c8da6d5 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,30 @@ +name: Run unit tests + +on: + push: + branches: + - main + pull_request: + branches: + - "*" + +jobs: + semgrep-scan: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install project requirements + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run unit tests + run: python -m unittest discover tests diff --git a/tests/.gitkeep b/tests/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_vault.py b/tests/test_vault.py new file mode 100644 index 0000000..e0241da --- /dev/null +++ b/tests/test_vault.py @@ -0,0 +1,38 @@ +"""Tests for Vault module""" + +import unittest +from unittest.mock import Mock, patch +import structlog + +from src.whispr.vault import SimpleVault + + +class SimpleVaultTest(unittest.TestCase): + """Tests for Vault""" + + def setUp(self): + # Mock logger and client to use in tests + self.mock_logger = Mock(spec=structlog.BoundLogger) + self.mock_client = Mock() + + # Subclass SimpleVault since it's abstract, only for testing + class TestVault(SimpleVault): + def fetch_secrets(self, secret_name: str) -> str: + # Provide a simple implementation for the abstract method + return "test_secret" + + self.vault = TestVault(logger=self.mock_logger, client=self.mock_client) + + @patch.object( + SimpleVault, "__abstractmethods__", set() + ) # This allows instantiation of SimpleVault directly if needed + def test_initialization(self): + """Test if the SimpleVault initializes with logger and client.""" + self.assertEqual(self.vault.logger, self.mock_logger) + self.assertEqual(self.vault.client, self.mock_client) + + def test_fetch_secrets(self): + """Test the fetch_secrets method to ensure it returns the expected result.""" + secret_name = "my_secret" + result = self.vault.fetch_secrets(secret_name) + self.assertEqual(result, "test_secret") From 9d40a5601c291453dab73bc449ca5fe971c6a524 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 08:59:58 -0700 Subject: [PATCH 02/17] tests: add unit test for aws module --- tests/test_aws.py | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 tests/test_aws.py diff --git a/tests/test_aws.py b/tests/test_aws.py new file mode 100644 index 0000000..f9f4819 --- /dev/null +++ b/tests/test_aws.py @@ -0,0 +1,77 @@ +import unittest +from unittest.mock import Mock, MagicMock, patch + +import botocore.exceptions +import structlog + +from src.whispr.vault import SimpleVault +from src.whispr.aws import AWSVault + + +class TestAWSVault(unittest.TestCase): + """Unit tests for AWSVault class, which fetches secrets from AWS Secrets Manager.""" + + def setUp(self): + """Set up mocks for logger and AWS client before each test.""" + self.mock_logger = MagicMock() + self.mock_client = MagicMock() + self.vault = AWSVault(logger=self.mock_logger, client=self.mock_client) + + def test_initialization(self): + """Test that AWSVault initializes with logger and client correctly.""" + self.assertEqual(self.vault.logger, self.mock_logger) + self.assertEqual(self.vault.client, self.mock_client) + + def test_fetch_secrets_success(self): + """Test successful fetch of secrets from AWS Secrets Manager.""" + self.mock_client.get_secret_value.return_value = { + "SecretString": '{"key": "value"}' + } + result = self.vault.fetch_secrets("test_secret") + self.assertEqual(result, '{"key": "value"}') + self.mock_client.get_secret_value.assert_called_with(SecretId="test_secret") + + def test_fetch_secrets_resource_not_found(self): + """Test fetch_secrets handles ResourceNotFoundException gracefully.""" + # Set up the client to raise ResourceNotFoundException + self.mock_client.get_secret_value.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "ResourceNotFoundException"}}, "get_secret_value" + ) + + result = self.vault.fetch_secrets("non_existent_secret") + self.assertEqual(result, "") + self.mock_logger.error.assert_called_with( + "The secret is not found on AWS. Did you set the right AWS_DEFAULT_REGION ?", + secret_name="non_existent_secret", + ) + + @patch("src.whispr.aws.AWSVault.fetch_secrets") + def test_fetch_secrets_unrecognized_client_exception(self, mock_fetch_secrets): + """Test fetch_secrets handles UnrecognizedClientException gracefully.""" + mock_fetch_secrets.side_effect = botocore.exceptions.ClientError( + {"Error": {"Code": "UnrecognizedClientException"}}, "get_secret_value" + ) + + with self.assertRaises(botocore.exceptions.ClientError): + result = self.vault.fetch_secrets("incorrect_credentials_secret") + self.assertEqual(result, "") + self.mock_logger.error.assert_called_with( + "Incorrect AWS credentials set for operation. Please verify them and retry." + ) + + def test_fetch_secrets_generic_exception(self): + """Test fetch_secrets raises exception and logs an error for generic exceptions.""" + # Set up the client to raise a generic exception + exception_message = "Some generic error" + self.mock_client.get_secret_value.side_effect = Exception(exception_message) + + with self.assertRaises(Exception) as context: + self.vault.fetch_secrets("generic_error_secret") + self.assertEqual(str(context.exception), exception_message) + + # Extract the actual call to the logger and check its arguments + self.assertTrue(self.mock_logger.error.called) + error_call = self.mock_logger.error.call_args + self.assertEqual(error_call[0][0], "Error fetching secret") + self.assertIsInstance(error_call[1]["error"], Exception) + self.assertEqual(str(error_call[1]["error"]), exception_message) From 0313c1f86bea0aba01fbf6a53ae3bd1a133aac69 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 09:00:33 -0700 Subject: [PATCH 03/17] tests: add unit tests for gcp module --- tests/test_gcp.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tests/test_gcp.py diff --git a/tests/test_gcp.py b/tests/test_gcp.py new file mode 100644 index 0000000..9295e16 --- /dev/null +++ b/tests/test_gcp.py @@ -0,0 +1,70 @@ +import unittest +from unittest.mock import Mock, patch, MagicMock + +import google.api_core.exceptions +import structlog + +from src.whispr.vault import SimpleVault +from src.whispr.gcp import GCPVault + + +class TestGCPVault(unittest.TestCase): + """Unit tests for GCPVault class, which fetches secrets from GCP Secrets Manager.""" + + def setUp(self): + """Set up mocks for logger, GCP client, and project_id before each test.""" + self.mock_logger = MagicMock() + self.mock_client = MagicMock() + self.project_id = "test_project_id" + self.vault = GCPVault( + logger=self.mock_logger, client=self.mock_client, project_id=self.project_id + ) + + def test_initialization(self): + """Test that GCPVault initializes with logger, client, and project_id correctly.""" + self.assertEqual(self.vault.logger, self.mock_logger) + self.assertEqual(self.vault.client, self.mock_client) + self.assertEqual(self.vault.project_id, self.project_id) + + def test_fetch_secrets_success(self): + """Test successful fetch of secrets from GCP Secrets Manager.""" + # Mock the client response + mock_response = MagicMock() + mock_response.payload.data.decode.return_value = '{"key": "value"}' + self.mock_client.access_secret_version.return_value = mock_response + + result = self.vault.fetch_secrets("test_secret") + self.assertEqual(result, '{"key": "value"}') + self.mock_logger.info.assert_called_with( + "Successfully fetched gcp secret: projects/test_project_id/secrets/test_secret/versions/latest" + ) + self.mock_client.access_secret_version.assert_called_with( + name="projects/test_project_id/secrets/test_secret/versions/latest" + ) + + def test_fetch_secrets_not_found(self): + """Test fetch_secrets handles NotFound exception gracefully.""" + # Set up the client to raise NotFound exception + self.mock_client.access_secret_version.side_effect = ( + google.api_core.exceptions.NotFound("Secret not found") + ) + + result = self.vault.fetch_secrets("non_existent_secret") + self.assertEqual(result, "") + self.mock_logger.error.assert_called_with( + "The given secret: projects/test_project_id/secrets/non_existent_secret/versions/latest is not found on gcp vault." + ) + + def test_fetch_secrets_generic_exception(self): + """Test fetch_secrets handles generic exceptions gracefully.""" + # Set up the client to raise a generic exception + exception_message = "Some generic error" + self.mock_client.access_secret_version.side_effect = Exception( + exception_message + ) + + result = self.vault.fetch_secrets("generic_error_secret") + self.assertEqual(result, "") + self.mock_logger.error.assert_called_with( + f"Error encountered while fetching secret: projects/test_project_id/secrets/generic_error_secret/versions/latest, Error: {exception_message}" + ) From 3b8d67bbff3d0b8ed00bb0cadda3373716f3a226 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 09:03:16 -0700 Subject: [PATCH 04/17] refactor: add module-level doc comments for tests --- tests/test_aws.py | 2 ++ tests/test_gcp.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/test_aws.py b/tests/test_aws.py index f9f4819..63b620d 100644 --- a/tests/test_aws.py +++ b/tests/test_aws.py @@ -1,3 +1,5 @@ +"""Tests for AWS module""" + import unittest from unittest.mock import Mock, MagicMock, patch diff --git a/tests/test_gcp.py b/tests/test_gcp.py index 9295e16..f647e12 100644 --- a/tests/test_gcp.py +++ b/tests/test_gcp.py @@ -1,3 +1,5 @@ +"""Tests for GCP module""" + import unittest from unittest.mock import Mock, patch, MagicMock From 192998488e094a6dba253d276f3a843876373bc3 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 09:17:21 -0700 Subject: [PATCH 05/17] ci: add src to Python env --- .github/workflows/test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c8da6d5..ef1dbec 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,8 @@ on: pull_request: branches: - "*" - +env: + PYTHONPATH: ./src # Needed for tests to discover whispr package jobs: semgrep-scan: runs-on: ubuntu-22.04 From 621fb5d1e340b4a66b9ad3e6ac41c8f3c2c18675 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 09:33:18 -0700 Subject: [PATCH 06/17] tests: use pytest as a test runner --- .github/workflows/test.yml | 4 ++-- requirements_test.txt | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 requirements_test.txt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ef1dbec..e991ea7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,7 @@ jobs: - name: Install project requirements run: | python -m pip install --upgrade pip - pip install -r requirements.txt + pip install -r requirements_test.txt - name: Run unit tests - run: python -m unittest discover tests + run: pytest tests diff --git a/requirements_test.txt b/requirements_test.txt new file mode 100644 index 0000000..0196252 --- /dev/null +++ b/requirements_test.txt @@ -0,0 +1,3 @@ +-r requirements.txt +coverage==7.6.4 +pytest==8.3.3 From 8686f3c25cfd2520dc45789ac32c8037aef66af8 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 09:51:53 -0700 Subject: [PATCH 07/17] tests: update imports in tests --- .github/workflows/test.yml | 2 +- tests/test_aws.py | 8 ++++---- tests/test_gcp.py | 6 +++--- tests/test_vault.py | 5 +++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e991ea7..599513e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ on: env: PYTHONPATH: ./src # Needed for tests to discover whispr package jobs: - semgrep-scan: + test: runs-on: ubuntu-22.04 steps: diff --git a/tests/test_aws.py b/tests/test_aws.py index 63b620d..12c3e89 100644 --- a/tests/test_aws.py +++ b/tests/test_aws.py @@ -6,11 +6,11 @@ import botocore.exceptions import structlog -from src.whispr.vault import SimpleVault -from src.whispr.aws import AWSVault +from whispr.vault import SimpleVault +from whispr.aws import AWSVault -class TestAWSVault(unittest.TestCase): +class AWSVaultTestCase(unittest.TestCase): """Unit tests for AWSVault class, which fetches secrets from AWS Secrets Manager.""" def setUp(self): @@ -47,7 +47,7 @@ def test_fetch_secrets_resource_not_found(self): secret_name="non_existent_secret", ) - @patch("src.whispr.aws.AWSVault.fetch_secrets") + @patch("whispr.aws.AWSVault.fetch_secrets") def test_fetch_secrets_unrecognized_client_exception(self, mock_fetch_secrets): """Test fetch_secrets handles UnrecognizedClientException gracefully.""" mock_fetch_secrets.side_effect = botocore.exceptions.ClientError( diff --git a/tests/test_gcp.py b/tests/test_gcp.py index f647e12..71c70c0 100644 --- a/tests/test_gcp.py +++ b/tests/test_gcp.py @@ -6,11 +6,11 @@ import google.api_core.exceptions import structlog -from src.whispr.vault import SimpleVault -from src.whispr.gcp import GCPVault +from whispr.vault import SimpleVault +from whispr.gcp import GCPVault -class TestGCPVault(unittest.TestCase): +class GCPVaultTestCase(unittest.TestCase): """Unit tests for GCPVault class, which fetches secrets from GCP Secrets Manager.""" def setUp(self): diff --git a/tests/test_vault.py b/tests/test_vault.py index e0241da..c94b3c6 100644 --- a/tests/test_vault.py +++ b/tests/test_vault.py @@ -2,12 +2,13 @@ import unittest from unittest.mock import Mock, patch + import structlog -from src.whispr.vault import SimpleVault +from whispr.vault import SimpleVault -class SimpleVaultTest(unittest.TestCase): +class SimpleVaultTestCase(unittest.TestCase): """Tests for Vault""" def setUp(self): From 958366deeb5ecbaac5297481ae92bc27ec9b7f70 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 15:04:36 -0700 Subject: [PATCH 08/17] tests: add unit tests for azure module --- tests/test_azure.py | 74 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tests/test_azure.py diff --git a/tests/test_azure.py b/tests/test_azure.py new file mode 100644 index 0000000..2caf9a4 --- /dev/null +++ b/tests/test_azure.py @@ -0,0 +1,74 @@ +"""Tests for Azure module""" + +import unittest +from unittest.mock import Mock, MagicMock + +import structlog +from azure.core.exceptions import ResourceNotFoundError + +from whispr.vault import SimpleVault +from whispr.azure import AzureVault + + +class AzureVaultTestCase(unittest.TestCase): + """Unit tests for AzureVault class, which fetches secrets from Azure Key Vault.""" + + def setUp(self): + """Set up mocks for logger, Azure client, and vault URL before each test.""" + self.mock_logger = MagicMock() + self.mock_client = MagicMock() + self.vault_url = "https://example-vault.vault.azure.net/" + self.vault = AzureVault( + logger=self.mock_logger, client=self.mock_client, vault_url=self.vault_url + ) + + def test_initialization(self): + """Test that AzureVault initializes with logger, client, and vault_url correctly.""" + self.assertEqual(self.vault.logger, self.mock_logger) + self.assertEqual(self.vault.client, self.mock_client) + self.assertEqual(self.vault.vault_url, self.vault_url) + + def test_fetch_secrets_success(self): + """Test successful fetch of secrets from Azure Key Vault.""" + # Mock the client response + mock_secret = MagicMock() + mock_secret.value = '{"key": "value"}' + self.mock_client.get_secret.return_value = mock_secret + + result = self.vault.fetch_secrets("test_secret") + self.assertEqual(result, '{"key": "value"}') + self.mock_logger.info.assert_called_with( + "Successfully fetched secret: test_secret" + ) + self.mock_client.get_secret.assert_called_with("test_secret") + + def test_fetch_secrets_resource_not_found(self): + """Test fetch_secrets handles ResourceNotFoundError gracefully.""" + # Set up the client to raise ResourceNotFoundError + self.mock_client.get_secret.side_effect = ResourceNotFoundError( + "Secret not found" + ) + + result = self.vault.fetch_secrets("non_existent_secret") + self.assertEqual(result, "") + self.mock_logger.error.assert_called_with( + "The given secret: non_existent_secret is not found on azure vault. Please check the secret name, vault name or subscription ID." + ) + + def test_fetch_secrets_generic_exception(self): + """Test fetch_secrets raises exception and logs an error for generic exceptions.""" + # Set up the client to raise a generic exception + exception_message = "Some generic error" + self.mock_client.get_secret.side_effect = Exception(exception_message) + + with self.assertRaises(Exception) as context: + self.vault.fetch_secrets("generic_error_secret") + self.assertEqual(str(context.exception), exception_message) + + # Extract the actual call to the logger and check its arguments + self.assertTrue(self.mock_logger.error.called) + error_call = self.mock_logger.error.call_args + self.assertEqual( + error_call[0][0], + f"Error fetching secret: generic_error_secret, Error: {exception_message}", + ) From b37eba829368ebe205012bed748e31a2dfce0a3e Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 15:45:58 -0700 Subject: [PATCH 09/17] test: add code coverall coverage --- .github/workflows/test.yml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 599513e..3fa9056 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,10 +22,21 @@ jobs: with: python-version: "3.10" - - name: Install project requirements + - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements_test.txt + pip install python-dateutil pytest mock pytest-cov coverage coveragepy-lcov - - name: Run unit tests - run: pytest tests + - name: Run Test + run: | + pytest --cov coveralls --cov-report term-missing --cov=resources tests/ + + - name: Covert to lcov + run: | + coveragepy-lcov + + - name: Coveralls GitHub Action + uses: coverallsapp/github-action@1.1.3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: lcov.info From 729ed40cf8067fb0083e0954c6b96e489cbcc6e8 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 15:47:57 -0700 Subject: [PATCH 10/17] test: install requirements --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3fa9056..a98b6a3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,6 +25,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip + pip install -r requirements.txt pip install python-dateutil pytest mock pytest-cov coverage coveragepy-lcov - name: Run Test From cded52d01fcba8afc20aa69a3d1db872503088a6 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 16:02:49 -0700 Subject: [PATCH 11/17] refactor: update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9660c5d..45317f4 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ lib64/ # Secrets .env *.creds +.coverage* From 48f8afeedd886c44891a78d9c3d241332137472a Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 16:04:11 -0700 Subject: [PATCH 12/17] refactor: update pyproject.toml --- .github/workflows/test.yml | 17 ++++++----------- pyproject.toml | 5 +++-- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a98b6a3..9c9ebd2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,19 +25,14 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements.txt - pip install python-dateutil pytest mock pytest-cov coverage coveragepy-lcov + pip install -r requirements_test.txt - name: Run Test run: | - pytest --cov coveralls --cov-report term-missing --cov=resources tests/ + coverage run -m pytest tests - - name: Covert to lcov - run: | - coveragepy-lcov - - - name: Coveralls GitHub Action - uses: coverallsapp/github-action@1.1.3 + - name: Upload coverage to Coveralls + uses: AndreMiras/coveralls-python-action@develop with: - github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: lcov.info + parallel: true + flag-name: Unit Test diff --git a/pyproject.toml b/pyproject.toml index 0053d2a..1dfd380 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ dependencies = [ "structlog==24.4.0", "azure-keyvault==4.2.0", "azure-identity==1.19.0", - "hvac==2.3.0" + "hvac==2.3.0", ] [project.urls] Documentation = "https://github.com/narenaryan/whispr/blob/main/README.md" @@ -60,9 +60,10 @@ python = ["3.8", "3.9", "3.10", "3.11", "3.12"] dependencies = ["mypy>=1.0.0"] [tool.coverage.run] -source_pkgs = ["whispr", "tests"] +source_pkgs = ["whispr"] branch = true parallel = true +relative_files = true omit = ["src/whispr/__about__.py"] [tool.coverage.paths] From 79948243fb4060bab45813be67c87d70af922caa Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 16:09:08 -0700 Subject: [PATCH 13/17] refactor: update coverall logic --- .github/workflows/test.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9c9ebd2..c503422 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,13 +26,9 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements_test.txt + pip install coveralls - name: Run Test run: | coverage run -m pytest tests - - - name: Upload coverage to Coveralls - uses: AndreMiras/coveralls-python-action@develop - with: - parallel: true - flag-name: Unit Test + coveralls From 87dadb734f10e0411d21549a8b2a6380446a21e7 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 16:10:47 -0700 Subject: [PATCH 14/17] ci: set github token for coverall step --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c503422..5c012df 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,6 +29,8 @@ jobs: pip install coveralls - name: Run Test + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | coverage run -m pytest tests coveralls From f63db4b984604d0f36fa65dc966f81d66e6e99b4 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 16:17:11 -0700 Subject: [PATCH 15/17] ci: update test workflow --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5c012df..89be41d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,5 +32,5 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - coverage run -m pytest tests + coverage run --source=whispr -m pytest tests/ coveralls From abbf7490717e43f48302710ffc251e22db4167f4 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 16:22:09 -0700 Subject: [PATCH 16/17] feat: add pytest cov plugin to generate coverage --- .github/workflows/test.yml | 2 +- requirements_test.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 89be41d..6e57875 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,5 +32,5 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - coverage run --source=whispr -m pytest tests/ + pytest --cov=whispr tests coveralls diff --git a/requirements_test.txt b/requirements_test.txt index 0196252..6915f0c 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,3 +1,4 @@ -r requirements.txt coverage==7.6.4 pytest==8.3.3 +pytest-cov==5.0.0 From 37d8e9d662a1b893189244484a0e6bf2a4efcd34 Mon Sep 17 00:00:00 2001 From: N3N Date: Sat, 26 Oct 2024 16:24:19 -0700 Subject: [PATCH 17/17] docs: add coverall badge --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 18e7ca4..6e6ad76 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ [![Downloads](https://static.pepy.tech/badge/whispr/month)](https://pepy.tech/project/whispr) +[![Coverage Status](https://coveralls.io/repos/github/narenaryan/whispr/badge.svg)](https://coveralls.io/github/narenaryan/whispr) # Whispr ![Logo](./logo.png) -Whispr (Pronounced as whisp-r) is a CLI tool to safely inject secrets from your favorite secret vault (Ex: AWS Secrets Manager, Azure Key Vault etc.) into your app's environment. This is very useful for enabling secure local software development. +Whispr (Pronounced as whisper) is a CLI tool to safely inject secrets from your favorite secret vault (Ex: AWS Secrets Manager, Azure Key Vault etc.) into your app's environment. This is very useful for enabling secure local software development. Whispr uses keys (with empty values) specified in a `.env` file and fetches respective secrets from a vault, and sets them as environment variables before launching an application. @@ -45,7 +46,7 @@ pip install whispr Run `whispr init ` in your terminal to create a `whispr.yaml` file in your project root. This file will store your configuration settings. -The available vault types are: `aws`, `azure`, and `gcp`. +The available vault types are: `aws`, `azure`, and `gcp`. **Example whispr.yaml contents (For: AWS):** ```yaml @@ -71,7 +72,7 @@ POSTGRES_PASSWORD= * Authenticate to AWS using Short-term credentials. * Alternatively, set temporary AWS credentials using a config file or environment variables. - + **Note**: Use respective authentication methods for other vaults. ## Launch any Application using Whispr