From 7a784d55f9cc222ac991a5df809ec7a1f3bdfa35 Mon Sep 17 00:00:00 2001 From: Pascal Zimmermann Date: Thu, 15 Jan 2026 20:18:53 +0100 Subject: [PATCH 1/2] feat: Add integrationtests --- .github/workflows/integration-tests.yml | 271 +++++++++++++++++++ .github/workflows/pull-request-checks.yml | 2 +- action.yml | 7 +- tests/test_integration.py | 314 ++++++++++++++++++++++ 4 files changed, 591 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/integration-tests.yml create mode 100644 tests/test_integration.py diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml new file mode 100644 index 0000000..173fc71 --- /dev/null +++ b/.github/workflows/integration-tests.yml @@ -0,0 +1,271 @@ +name: Integration Tests + +on: + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + # Test the action itself in a real scenario + test-action-usage: + runs-on: ubuntu-latest + name: Test Action - Check Changed Files + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create test changes in src directory + run: | + echo "# Test change" >> src/test_file.py + echo "print('test')" >> src/another_test.py + + - name: Run check-changed-files-action for src directory + id: check-src + uses: ./ + with: + checked_location: 'src/' + git_location: './' + + - name: Verify src changes detected + run: | + git status + echo "Files changed in src: ${{ steps.check-src.outputs.files_changed }}" + if [ "${{ steps.check-src.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for src/ changes" + exit 1 + fi + + - name: Create test changes in docs directory + run: | + mkdir -p docs + echo "# Documentation" >> docs/test.md + + - name: Run check-changed-files-action for docs directory + id: check-docs + uses: ./ + with: + checked_location: 'docs/' + git_location: './' + + - name: Verify docs changes detected + run: | + echo "Files changed in docs: ${{ steps.check-docs.outputs.files_changed }}" + if [ "${{ steps.check-docs.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for docs/ changes" + exit 1 + fi + + - name: Run check-changed-files-action for non-existent directory + id: check-nonexistent + uses: ./ + with: + checked_location: 'nonexistent/' + git_location: './' + check_all_files: 'false' + + - name: Verify non-existent directory returns false + run: | + echo "Files changed in nonexistent: ${{ steps.check-nonexistent.outputs.files_changed }}" + # This should be false since we didn't change files in nonexistent/ + # (we have changes in src/ and docs/, but not in nonexistent/) + + # Test with check_all_files flag + test-action-check-all-files: + runs-on: ubuntu-latest + name: Test Action - Check All Files Mode + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create test changes in allowed directories + run: | + echo "# Test change in src" >> src/test_src.py + echo "# Test change in tests" >> tests/test_integration_new.py + + - name: Run check-changed-files-action with check_all_files=true + id: check-all-allowed + uses: ./ + with: + checked_location: 'src/;tests/' + git_location: './' + check_all_files: 'true' + + - name: Verify all files in allowed locations + run: | + echo "All files allowed: ${{ steps.check-all-allowed.outputs.files_changed }}" + if [ "${{ steps.check-all-allowed.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true when all files are in allowed locations" + exit 1 + fi + + - name: Create change in non-allowed directory + run: | + mkdir -p config + echo "key: value" >> config/settings.yml + + - name: Run check-changed-files-action with mixed locations + id: check-all-mixed + uses: ./ + with: + checked_location: 'src/;tests/' + git_location: './' + check_all_files: 'true' + + - name: Verify mixed locations fail with check_all_files=true + run: | + echo "Mixed locations result: ${{ steps.check-all-mixed.outputs.files_changed }}" + if [ "${{ steps.check-all-mixed.outputs.files_changed }}" != "false" ]; then + echo "ERROR: Expected files_changed=false when not all files are in allowed locations" + exit 1 + fi + + # Test with multiple semicolon-separated locations + test-action-multiple-locations: + runs-on: ubuntu-latest + name: Test Action - Multiple Locations + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create changes in multiple directories + run: | + echo "# Change 1" >> src/file1.py + echo "# Change 2" >> tests/file2.py + mkdir -p docs + echo "# Change 3" >> docs/file3.md + + - name: Run check-changed-files-action with multiple locations + id: check-multiple + uses: ./ + with: + checked_location: 'src/;tests/;docs/' + git_location: './' + check_all_files: 'true' + + - name: Verify multiple locations work + run: | + echo "Multiple locations result: ${{ steps.check-multiple.outputs.files_changed }}" + if [ "${{ steps.check-multiple.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for multiple allowed locations" + exit 1 + fi + + # Test with specific file patterns + test-action-specific-files: + runs-on: ubuntu-latest + name: Test Action - Specific File Patterns + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Modify README.md + run: | + echo "# Updated README" >> README.md + + - name: Run check-changed-files-action for specific file + id: check-readme + uses: ./ + with: + checked_location: 'README.md' + git_location: './' + check_all_files: 'false' + + - name: Verify specific file detection + run: | + echo "README.md changed: ${{ steps.check-readme.outputs.files_changed }}" + if [ "${{ steps.check-readme.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for README.md" + exit 1 + fi + + - name: Modify action.yml + run: | + echo "# Comment" >> action.yml + + - name: Run check-changed-files-action for action.yml + id: check-action + uses: ./ + with: + checked_location: 'action.yml' + git_location: './' + check_all_files: 'false' + + - name: Verify action.yml detection + run: | + echo "action.yml changed: ${{ steps.check-action.outputs.files_changed }}" + if [ "${{ steps.check-action.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for action.yml" + exit 1 + fi + + # Test with GitHub Enterprise scenario (using token) + test-action-with-token: + runs-on: ubuntu-latest + name: Test Action - With GitHub Token + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create test change + run: | + echo "# Test with token" >> src/token_test.py + + - name: Run check-changed-files-action with token + id: check-with-token + uses: ./ + with: + checked_location: 'src/' + git_location: './' + check_all_files: 'false' + github_user_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Verify token scenario works + run: | + echo "With token result: ${{ steps.check-with-token.outputs.files_changed }}" + if [ "${{ steps.check-with-token.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true with token" + exit 1 + fi + + # Run Python integration tests + run-python-integration-tests: + runs-on: ubuntu-latest + name: Run Python Integration Tests + strategy: + matrix: + python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + cache: 'pip' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run integration tests + run: | + PYTHONPATH=src python -m unittest tests.test_integration -v diff --git a/.github/workflows/pull-request-checks.yml b/.github/workflows/pull-request-checks.yml index 916c14f..02b4194 100644 --- a/.github/workflows/pull-request-checks.yml +++ b/.github/workflows/pull-request-checks.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.12' ] + python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14' ] steps: - uses: actions/checkout@v6 diff --git a/action.yml b/action.yml index d8e5e56..94be92b 100644 --- a/action.yml +++ b/action.yml @@ -74,7 +74,10 @@ runs: REF_PATH="main" fi - curl -s -L -o /tmp/check_changed_files.py "https://${AUTH_PREFIX}raw.githubusercontent.com/ZPascal/check-changed-files-action/$REF_PATH/src/check_changed_files.py" + if ! curl -f -s -L -o /tmp/check_changed_files.py "https://${AUTH_PREFIX}raw.githubusercontent.com/ZPascal/check-changed-files-action/$REF_PATH/src/check_changed_files.py"; then + echo "Error: Failed to download check_changed_files.py script" + exit 1 + fi optional_flags="" if [ -n "${{ inputs.git_location }}" ]; then @@ -83,5 +86,5 @@ runs: if [ "${{ inputs.check_all_files }}" == "true" ]; then optional_flags+=" -caf" fi - echo "changed-files='$(python3 /tmp/check_changed_files.py -cl '${{ inputs.checked_location }}' $optional_flags)'" >> "$GITHUB_OUTPUT" + echo "changed-files=$(python3 /tmp/check_changed_files.py -cl '${{ inputs.checked_location }}' $optional_flags)" >> "$GITHUB_OUTPUT" shell: bash diff --git a/tests/test_integration.py b/tests/test_integration.py new file mode 100644 index 0000000..f6c6e29 --- /dev/null +++ b/tests/test_integration.py @@ -0,0 +1,314 @@ +#!/usr/bin/env python +""" +Integration tests for the Check Changed Files GitHub Action. + +These tests create real Git repositories and verify the action's behavior +in realistic scenarios. +""" + +import os +import shutil +import tempfile +import unittest +from unittest.mock import patch +import argparse + +from pygit2 import Repository, init_repository, Signature + +from check_changed_files import CheckedChangedFiles + + +class TestCheckChangedFilesIntegration(unittest.TestCase): + """Integration tests for CheckedChangedFiles with real Git repositories.""" + + def setUp(self): + """Create a temporary directory for test repositories.""" + self.test_dir = tempfile.mkdtemp() + self.original_cwd = os.getcwd() + + def tearDown(self): + """Clean up temporary directory after tests.""" + os.chdir(self.original_cwd) + shutil.rmtree(self.test_dir, ignore_errors=True) + + def _create_git_repo(self, repo_path: str) -> Repository: + """ + Create a new Git repository with an initial commit. + + Args: + repo_path: Path where the repository should be created + + Returns: + Repository: The initialized repository + """ + repo = init_repository(repo_path) + + # Create an initial commit + signature = Signature("Test User", "test@example.com") + + # Create initial file + initial_file = os.path.join(repo_path, "README.md") + with open(initial_file, "w") as f: + f.write("# Test Repository\n") + + # Add and commit + repo.index.add("README.md") + repo.index.write() + tree = repo.index.write_tree() + repo.create_commit("HEAD", signature, signature, "Initial commit", tree, []) + + return repo + + def _modify_file(self, repo_path: str, file_path: str, content: str): + """ + Modify or create a file in the repository. + + Args: + repo_path: Path to the repository + file_path: Relative path to the file + content: Content to write to the file + """ + full_path = os.path.join(repo_path, file_path) + os.makedirs(os.path.dirname(full_path), exist_ok=True) + with open(full_path, "w") as f: + f.write(content) + + def test_integration_single_file_changed_in_allowed_location(self): + """Test that a single file change in an allowed location is detected.""" + repo_path = os.path.join(self.test_dir, "test_repo_1") + self._create_git_repo(repo_path) + + # Modify a file in the src directory + self._modify_file(repo_path, "src/main.py", 'print("Hello World")\n') + + # Test the action + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/", git_location=repo_path, check_all_files=False + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertTrue(result) + + def test_integration_single_file_changed_in_disallowed_location(self): + """Test that a single file change in a disallowed location is detected.""" + repo_path = os.path.join(self.test_dir, "test_repo_2") + self._create_git_repo(repo_path) + + # Modify a file in the docs directory + self._modify_file(repo_path, "docs/guide.md", "# User Guide\n") + + # Test the action with only src/ allowed + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/", git_location=repo_path, check_all_files=False + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertFalse(result) + + def test_integration_multiple_files_all_allowed(self): + """Test multiple file changes where all are in allowed locations.""" + repo_path = os.path.join(self.test_dir, "test_repo_3") + self._create_git_repo(repo_path) + + # Modify multiple files in allowed directories + self._modify_file(repo_path, "src/main.py", 'print("Hello")\n') + self._modify_file(repo_path, "src/utils.py", "def helper(): pass\n") + self._modify_file(repo_path, "tests/test_main.py", "def test(): pass\n") + + # Test with check_all_files=True + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/;tests/", + git_location=repo_path, + check_all_files=True, + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertTrue(result) + + def test_integration_multiple_files_mixed_locations_check_all_files(self): + """Test multiple file changes with mixed allowed/disallowed locations and check_all_files=True.""" + repo_path = os.path.join(self.test_dir, "test_repo_4") + self._create_git_repo(repo_path) + + # Modify files in both allowed and disallowed directories + self._modify_file(repo_path, "src/main.py", 'print("Hello")\n') + self._modify_file(repo_path, "config/settings.yml", "key: value\n") + + # Test with check_all_files=True - should fail because config/ is not allowed + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/", git_location=repo_path, check_all_files=True + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertFalse(result) + + def test_integration_multiple_files_mixed_locations_check_any_file(self): + """Test multiple file changes with mixed allowed/disallowed locations and check_all_files=False.""" + repo_path = os.path.join(self.test_dir, "test_repo_5") + self._create_git_repo(repo_path) + + # Modify files in both allowed and disallowed directories + self._modify_file(repo_path, "src/main.py", 'print("Hello")\n') + self._modify_file(repo_path, "config/settings.yml", "key: value\n") + + # Test with check_all_files=False - should succeed because at least one file is allowed + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/", git_location=repo_path, check_all_files=False + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertTrue(result) + + def test_integration_no_changes(self): + """Test repository with no changes.""" + repo_path = os.path.join(self.test_dir, "test_repo_6") + self._create_git_repo(repo_path) + + # Don't modify any files + + # Test the action + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/", git_location=repo_path, check_all_files=False + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertFalse(result) + + def test_integration_nested_directory_structure(self): + """Test with deeply nested directory structures.""" + repo_path = os.path.join(self.test_dir, "test_repo_7") + self._create_git_repo(repo_path) + + # Create deeply nested structure + self._modify_file( + repo_path, "src/components/ui/button/Button.py", "class Button: pass\n" + ) + self._modify_file( + repo_path, "src/utils/helpers/string_helpers.py", "def trim(): pass\n" + ) + + # Test the action + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/", git_location=repo_path, check_all_files=True + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertTrue(result) + + def test_integration_specific_file_pattern(self): + """Test with specific file patterns in checked_location.""" + repo_path = os.path.join(self.test_dir, "test_repo_8") + self._create_git_repo(repo_path) + + # Modify specific files + self._modify_file(repo_path, "docs/README.md", "# Updated README\n") + self._modify_file(repo_path, "docs/guide.md", "# Guide\n") + + # Test the action with specific file in checked_location + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="docs/README.md", + git_location=repo_path, + check_all_files=False, + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertTrue(result) + + def test_integration_multiple_semicolon_separated_locations(self): + """Test with multiple semicolon-separated locations.""" + repo_path = os.path.join(self.test_dir, "test_repo_9") + self._create_git_repo(repo_path) + + # Modify files in different directories + self._modify_file(repo_path, "src/main.py", 'print("Hello")\n') + self._modify_file(repo_path, "docs/api.md", "# API\n") + self._modify_file(repo_path, "tests/test_api.py", "def test(): pass\n") + + # Test the action with multiple locations + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/;docs/;tests/", + git_location=repo_path, + check_all_files=True, + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertTrue(result) + + def test_integration_file_deletion(self): + """Test detection of deleted files.""" + repo_path = os.path.join(self.test_dir, "test_repo_10") + repo = self._create_git_repo(repo_path) + + # Create and commit a file first + signature = Signature("Test User", "test@example.com") + self._modify_file(repo_path, "src/old_file.py", 'print("Old")\n') + + repo.index.add("src/old_file.py") + repo.index.write() + tree = repo.index.write_tree() + parent = repo.head.target + repo.create_commit("HEAD", signature, signature, "Add old file", tree, [parent]) + + # Now delete the file + os.remove(os.path.join(repo_path, "src/old_file.py")) + + # Test the action + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/", git_location=repo_path, check_all_files=False + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertTrue(result) + + def test_integration_new_file_creation(self): + """Test detection of newly created files.""" + repo_path = os.path.join(self.test_dir, "test_repo_11") + self._create_git_repo(repo_path) + + # Create a new file (not committed) + self._modify_file(repo_path, "src/new_feature.py", "def new_feature(): pass\n") + + # Test the action + with patch("argparse.ArgumentParser.parse_args") as mock_args: + mock_args.return_value = argparse.Namespace( + checked_location="src/", git_location=repo_path, check_all_files=False + ) + + checker = CheckedChangedFiles() + result = checker.files_changed() + + self.assertTrue(result) + + +if __name__ == "__main__": + unittest.main() From 3b69bb9c2d567946641279a435dd1faedaf61cf9 Mon Sep 17 00:00:00 2001 From: Pascal Zimmermann Date: Tue, 20 Jan 2026 11:45:14 +0100 Subject: [PATCH 2/2] feat: Restructure the tests --- .github/workflows/integration-tests.yml | 271 --------------------- .github/workflows/pull-request-checks.yml | 275 +++++++++++++++++++++- 2 files changed, 274 insertions(+), 272 deletions(-) delete mode 100644 .github/workflows/integration-tests.yml diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml deleted file mode 100644 index 173fc71..0000000 --- a/.github/workflows/integration-tests.yml +++ /dev/null @@ -1,271 +0,0 @@ -name: Integration Tests - -on: - pull_request: - branches: [ main ] - workflow_dispatch: - -jobs: - # Test the action itself in a real scenario - test-action-usage: - runs-on: ubuntu-latest - name: Test Action - Check Changed Files - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Create test changes in src directory - run: | - echo "# Test change" >> src/test_file.py - echo "print('test')" >> src/another_test.py - - - name: Run check-changed-files-action for src directory - id: check-src - uses: ./ - with: - checked_location: 'src/' - git_location: './' - - - name: Verify src changes detected - run: | - git status - echo "Files changed in src: ${{ steps.check-src.outputs.files_changed }}" - if [ "${{ steps.check-src.outputs.files_changed }}" != "true" ]; then - echo "ERROR: Expected files_changed=true for src/ changes" - exit 1 - fi - - - name: Create test changes in docs directory - run: | - mkdir -p docs - echo "# Documentation" >> docs/test.md - - - name: Run check-changed-files-action for docs directory - id: check-docs - uses: ./ - with: - checked_location: 'docs/' - git_location: './' - - - name: Verify docs changes detected - run: | - echo "Files changed in docs: ${{ steps.check-docs.outputs.files_changed }}" - if [ "${{ steps.check-docs.outputs.files_changed }}" != "true" ]; then - echo "ERROR: Expected files_changed=true for docs/ changes" - exit 1 - fi - - - name: Run check-changed-files-action for non-existent directory - id: check-nonexistent - uses: ./ - with: - checked_location: 'nonexistent/' - git_location: './' - check_all_files: 'false' - - - name: Verify non-existent directory returns false - run: | - echo "Files changed in nonexistent: ${{ steps.check-nonexistent.outputs.files_changed }}" - # This should be false since we didn't change files in nonexistent/ - # (we have changes in src/ and docs/, but not in nonexistent/) - - # Test with check_all_files flag - test-action-check-all-files: - runs-on: ubuntu-latest - name: Test Action - Check All Files Mode - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Create test changes in allowed directories - run: | - echo "# Test change in src" >> src/test_src.py - echo "# Test change in tests" >> tests/test_integration_new.py - - - name: Run check-changed-files-action with check_all_files=true - id: check-all-allowed - uses: ./ - with: - checked_location: 'src/;tests/' - git_location: './' - check_all_files: 'true' - - - name: Verify all files in allowed locations - run: | - echo "All files allowed: ${{ steps.check-all-allowed.outputs.files_changed }}" - if [ "${{ steps.check-all-allowed.outputs.files_changed }}" != "true" ]; then - echo "ERROR: Expected files_changed=true when all files are in allowed locations" - exit 1 - fi - - - name: Create change in non-allowed directory - run: | - mkdir -p config - echo "key: value" >> config/settings.yml - - - name: Run check-changed-files-action with mixed locations - id: check-all-mixed - uses: ./ - with: - checked_location: 'src/;tests/' - git_location: './' - check_all_files: 'true' - - - name: Verify mixed locations fail with check_all_files=true - run: | - echo "Mixed locations result: ${{ steps.check-all-mixed.outputs.files_changed }}" - if [ "${{ steps.check-all-mixed.outputs.files_changed }}" != "false" ]; then - echo "ERROR: Expected files_changed=false when not all files are in allowed locations" - exit 1 - fi - - # Test with multiple semicolon-separated locations - test-action-multiple-locations: - runs-on: ubuntu-latest - name: Test Action - Multiple Locations - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Create changes in multiple directories - run: | - echo "# Change 1" >> src/file1.py - echo "# Change 2" >> tests/file2.py - mkdir -p docs - echo "# Change 3" >> docs/file3.md - - - name: Run check-changed-files-action with multiple locations - id: check-multiple - uses: ./ - with: - checked_location: 'src/;tests/;docs/' - git_location: './' - check_all_files: 'true' - - - name: Verify multiple locations work - run: | - echo "Multiple locations result: ${{ steps.check-multiple.outputs.files_changed }}" - if [ "${{ steps.check-multiple.outputs.files_changed }}" != "true" ]; then - echo "ERROR: Expected files_changed=true for multiple allowed locations" - exit 1 - fi - - # Test with specific file patterns - test-action-specific-files: - runs-on: ubuntu-latest - name: Test Action - Specific File Patterns - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Modify README.md - run: | - echo "# Updated README" >> README.md - - - name: Run check-changed-files-action for specific file - id: check-readme - uses: ./ - with: - checked_location: 'README.md' - git_location: './' - check_all_files: 'false' - - - name: Verify specific file detection - run: | - echo "README.md changed: ${{ steps.check-readme.outputs.files_changed }}" - if [ "${{ steps.check-readme.outputs.files_changed }}" != "true" ]; then - echo "ERROR: Expected files_changed=true for README.md" - exit 1 - fi - - - name: Modify action.yml - run: | - echo "# Comment" >> action.yml - - - name: Run check-changed-files-action for action.yml - id: check-action - uses: ./ - with: - checked_location: 'action.yml' - git_location: './' - check_all_files: 'false' - - - name: Verify action.yml detection - run: | - echo "action.yml changed: ${{ steps.check-action.outputs.files_changed }}" - if [ "${{ steps.check-action.outputs.files_changed }}" != "true" ]; then - echo "ERROR: Expected files_changed=true for action.yml" - exit 1 - fi - - # Test with GitHub Enterprise scenario (using token) - test-action-with-token: - runs-on: ubuntu-latest - name: Test Action - With GitHub Token - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Create test change - run: | - echo "# Test with token" >> src/token_test.py - - - name: Run check-changed-files-action with token - id: check-with-token - uses: ./ - with: - checked_location: 'src/' - git_location: './' - check_all_files: 'false' - github_user_token: ${{ secrets.GITHUB_TOKEN }} - - - name: Verify token scenario works - run: | - echo "With token result: ${{ steps.check-with-token.outputs.files_changed }}" - if [ "${{ steps.check-with-token.outputs.files_changed }}" != "true" ]; then - echo "ERROR: Expected files_changed=true with token" - exit 1 - fi - - # Run Python integration tests - run-python-integration-tests: - runs-on: ubuntu-latest - name: Run Python Integration Tests - strategy: - matrix: - python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14' ] - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 - with: - python-version: ${{ matrix.python-version }} - architecture: x64 - cache: 'pip' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - - name: Run integration tests - run: | - PYTHONPATH=src python -m unittest tests.test_integration -v diff --git a/.github/workflows/pull-request-checks.yml b/.github/workflows/pull-request-checks.yml index 02b4194..510cbaf 100644 --- a/.github/workflows/pull-request-checks.yml +++ b/.github/workflows/pull-request-checks.yml @@ -5,7 +5,6 @@ on: branches: [ main ] jobs: - pr-test: runs-on: ubuntu-latest strategy: @@ -51,3 +50,277 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} flake8_args: --config=.flake8 fail_level: "error" + + integrationtest-test-action-usage: + runs-on: ubuntu-latest + needs: [ pr-test, pr-lint ] + name: Integrationtest | Test Action - Check Changed Files + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create test changes in src directory + run: | + echo "# Test change" >> src/test_file.py + echo "print('test')" >> src/another_test.py + + - name: Run check-changed-files-action for src directory + id: check-src + uses: ./ + with: + checked_location: 'src/' + git_location: './' + + - name: Verify src changes detected + run: | + git status + echo "Files changed in src: ${{ steps.check-src.outputs.files_changed }}" + if [ "${{ steps.check-src.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for src/ changes" + exit 1 + fi + + - name: Create test changes in docs directory + run: | + mkdir -p docs + echo "# Documentation" >> docs/test.md + + - name: Run check-changed-files-action for docs directory + id: check-docs + uses: ./ + with: + checked_location: 'docs/' + git_location: './' + + - name: Verify docs changes detected + run: | + echo "Files changed in docs: ${{ steps.check-docs.outputs.files_changed }}" + if [ "${{ steps.check-docs.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for docs/ changes" + exit 1 + fi + + - name: Verify the GH if condition format works for docs + if: steps.check-docs.outputs.files_changed == 'true' + run: | + echo "Files changed: ${{ steps.check-docs.outputs.files_changed }}" + + - name: Run check-changed-files-action for non-existent directory + id: check-nonexistent + uses: ./ + with: + checked_location: 'nonexistent/' + git_location: './' + check_all_files: 'false' + + - name: Verify non-existent directory returns false + run: | + echo "Files changed in nonexistent: ${{ steps.check-nonexistent.outputs.files_changed }}" + # This should be false since we didn't change files in nonexistent/ + # (we have changes in src/ and docs/, but not in nonexistent/) + + - name: Verify the GH if condition format works for nonexistent + if: steps.check-nonexistent.outputs.files_changed == 'false' + run: | + echo "Files changed: ${{ steps.check-nonexistent.outputs.files_changed }}" + + integrationtest-test-action-check-all-files: + runs-on: ubuntu-latest + needs: [ pr-test, pr-lint ] + name: Integrationtest | Test Action - Check All Files Mode + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create test changes in allowed directories + run: | + echo "# Test change in src" >> src/test_src.py + echo "# Test change in tests" >> tests/test_integration_new.py + + - name: Run check-changed-files-action with check_all_files=true + id: check-all-allowed + uses: ./ + with: + checked_location: 'src/;tests/' + git_location: './' + check_all_files: 'true' + + - name: Verify all files in allowed locations + run: | + echo "All files allowed: ${{ steps.check-all-allowed.outputs.files_changed }}" + if [ "${{ steps.check-all-allowed.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true when all files are in allowed locations" + exit 1 + fi + + - name: Create change in non-allowed directory + run: | + mkdir -p config + echo "key: value" >> config/settings.yml + + - name: Run check-changed-files-action with mixed locations + id: check-all-mixed + uses: ./ + with: + checked_location: 'src/;tests/' + git_location: './' + check_all_files: 'true' + + - name: Verify mixed locations fail with check_all_files=true + run: | + echo "Mixed locations result: ${{ steps.check-all-mixed.outputs.files_changed }}" + if [ "${{ steps.check-all-mixed.outputs.files_changed }}" != "false" ]; then + echo "ERROR: Expected files_changed=false when not all files are in allowed locations" + exit 1 + fi + + integrationtest-test-action-multiple-locations: + runs-on: ubuntu-latest + needs: [ pr-test, pr-lint ] + name: Integrationtest | Test Action - Multiple Locations + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create changes in multiple directories + run: | + echo "# Change 1" >> src/file1.py + echo "# Change 2" >> tests/file2.py + mkdir -p docs + echo "# Change 3" >> docs/file3.md + + - name: Run check-changed-files-action with multiple locations + id: check-multiple + uses: ./ + with: + checked_location: 'src/;tests/;docs/' + git_location: './' + check_all_files: 'true' + + - name: Verify multiple locations work + run: | + echo "Multiple locations result: ${{ steps.check-multiple.outputs.files_changed }}" + if [ "${{ steps.check-multiple.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for multiple allowed locations" + exit 1 + fi + + integrationtest-test-action-specific-files: + runs-on: ubuntu-latest + needs: [ pr-test, pr-lint ] + name: Integrationtest | Test Action - Specific File Patterns + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Modify README.md + run: | + echo "# Updated README" >> README.md + + - name: Run check-changed-files-action for specific file + id: check-readme + uses: ./ + with: + checked_location: 'README.md' + git_location: './' + check_all_files: 'false' + + - name: Verify specific file detection + run: | + echo "README.md changed: ${{ steps.check-readme.outputs.files_changed }}" + if [ "${{ steps.check-readme.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for README.md" + exit 1 + fi + + - name: Modify LICENSE + run: | + echo "# Comment" >> LICENSE + + - name: Run check-changed-files-action for LICENSE + id: check-action + uses: ./ + with: + checked_location: 'LICENSE' + git_location: './' + check_all_files: 'false' + + - name: Verify LICENSE detection + run: | + echo "LICENSE changed: ${{ steps.check-action.outputs.files_changed }}" + if [ "${{ steps.check-action.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true for LICENSE" + exit 1 + fi + + integrationtest-test-action-with-token: + runs-on: ubuntu-latest + needs: [ pr-test, pr-lint ] + name: Integrationtest | Test Action - With GitHub Token + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create test change + run: | + echo "# Test with token" >> src/token_test.py + + - name: Run check-changed-files-action with token + id: check-with-token + uses: ./ + with: + checked_location: 'src/' + git_location: './' + check_all_files: 'false' + github_user_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Verify token scenario works + run: | + echo "With token result: ${{ steps.check-with-token.outputs.files_changed }}" + if [ "${{ steps.check-with-token.outputs.files_changed }}" != "true" ]; then + echo "ERROR: Expected files_changed=true with token" + exit 1 + fi + + integrationtest-run-python-integration-tests: + runs-on: ubuntu-latest + name: Integrationtest | Run Python Integration Tests + needs: [ pr-test, pr-lint ] + strategy: + matrix: + python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + cache: 'pip' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run integration tests + run: | + PYTHONPATH=src python -m unittest tests.test_integration -v