Skip to main content
Glama

PyGithub MCP Server

by AstroMined
"""Issue labels integration tests. This module tests the issue label operations using the real GitHub API. """ import pytest from datetime import datetime from pygithub_mcp_server.operations.issues import ( create_issue, update_issue, add_issue_labels, remove_issue_label, ) from pygithub_mcp_server.schemas.issues import ( CreateIssueParams, UpdateIssueParams, AddIssueLabelsParams, RemoveIssueLabelParams, ) @pytest.mark.integration def test_add_issue_labels(test_owner, test_repo_name, unique_id, with_retry): """Test adding labels to an issue.""" # Setup owner = test_owner repo = test_repo_name title = f"Test Issue (Add Labels) {unique_id}" # Create an issue @with_retry def create_test_issue(): return create_issue(CreateIssueParams( owner=owner, repo=repo, title=title )) issue = create_test_issue() try: # Add labels @with_retry def add_test_labels(): return add_issue_labels(AddIssueLabelsParams( owner=owner, repo=repo, issue_number=issue["issue_number"], labels=["bug", "enhancement"] )) labels = add_test_labels() # Verify assert isinstance(labels, list) assert len(labels) >= 2 label_names = [label["name"] for label in labels] assert "bug" in label_names assert "enhancement" in label_names finally: # Cleanup try: @with_retry def close_issue(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"], state="closed" )) close_issue() except Exception as e: print(f"Failed to close issue during cleanup: {e}") @pytest.mark.integration def test_remove_issue_label(test_owner, test_repo_name, unique_id, with_retry): """Test removing a label from an issue.""" # Setup owner = test_owner repo = test_repo_name title = f"Test Issue (Remove Label) {unique_id}" # Create an issue with labels @with_retry def create_test_issue(): issue = create_issue(CreateIssueParams( owner=owner, repo=repo, title=title )) add_issue_labels(AddIssueLabelsParams( owner=owner, repo=repo, issue_number=issue["issue_number"], labels=["bug", "enhancement"] )) return issue issue = create_test_issue() try: # Verify labels were added @with_retry def get_issue_with_labels(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"] )) # Using update with no changes to get current state issue_with_labels = get_issue_with_labels() label_names = [label["name"] for label in issue_with_labels["labels"]] assert "bug" in label_names assert "enhancement" in label_names # Remove one label @with_retry def remove_test_label(): return remove_issue_label(RemoveIssueLabelParams( owner=owner, repo=repo, issue_number=issue["issue_number"], label="bug" )) remove_test_label() # Verify label was removed @with_retry def get_issue_after_remove(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"] )) # Using update with no changes to get current state issue_after_remove = get_issue_after_remove() label_names_after = [label["name"] for label in issue_after_remove["labels"]] assert "bug" not in label_names_after assert "enhancement" in label_names_after finally: # Cleanup try: @with_retry def close_issue(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"], state="closed" )) close_issue() except Exception as e: print(f"Failed to close issue during cleanup: {e}") @pytest.mark.integration def test_add_issue_labels_multiple_calls(test_owner, test_repo_name, unique_id, with_retry): """Test adding labels to an issue with multiple calls.""" # Setup owner = test_owner repo = test_repo_name title = f"Test Issue (Add Labels Multiple) {unique_id}" # Create an issue @with_retry def create_test_issue(): return create_issue(CreateIssueParams( owner=owner, repo=repo, title=title )) issue = create_test_issue() try: # Add first label @with_retry def add_first_label(): return add_issue_labels(AddIssueLabelsParams( owner=owner, repo=repo, issue_number=issue["issue_number"], labels=["bug"] )) first_labels = add_first_label() # Verify assert isinstance(first_labels, list) assert any(label["name"] == "bug" for label in first_labels) # Add second label @with_retry def add_second_label(): return add_issue_labels(AddIssueLabelsParams( owner=owner, repo=repo, issue_number=issue["issue_number"], labels=["enhancement"] )) second_labels = add_second_label() # Verify both labels are present assert isinstance(second_labels, list) label_names = [label["name"] for label in second_labels] assert "bug" in label_names assert "enhancement" in label_names finally: # Cleanup try: @with_retry def close_issue(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"], state="closed" )) close_issue() except Exception as e: print(f"Failed to close issue during cleanup: {e}") @pytest.mark.integration def test_remove_nonexistent_label(test_owner, test_repo_name, unique_id, with_retry): """Test removing a non-existent label from an issue.""" # Setup owner = test_owner repo = test_repo_name title = f"Test Issue (Remove Nonexistent Label) {unique_id}" # Create an issue @with_retry def create_test_issue(): return create_issue(CreateIssueParams( owner=owner, repo=repo, title=title )) issue = create_test_issue() try: # Remove a non-existent label nonexistent_label = f"nonexistent-{unique_id}" @with_retry def remove_nonexistent_label(): # This should not raise an error, GitHub API silently ignores removing non-existent labels return remove_issue_label(RemoveIssueLabelParams( owner=owner, repo=repo, issue_number=issue["issue_number"], label=nonexistent_label )) # This should not raise an exception remove_nonexistent_label() # Verify issue state is still accessible @with_retry def get_issue_after_remove(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"] )) # Using update with no changes to get current state issue_after_remove = get_issue_after_remove() assert issue_after_remove["issue_number"] == issue["issue_number"] finally: # Cleanup try: @with_retry def close_issue(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"], state="closed" )) close_issue() except Exception as e: print(f"Failed to close issue during cleanup: {e}") @pytest.mark.integration def test_label_lifecycle(test_owner, test_repo_name, unique_id, with_retry): """Test complete label lifecycle (add → verify → remove → verify).""" # Setup owner = test_owner repo = test_repo_name title = f"Test Issue (Label Lifecycle) {unique_id}" # Create an issue @with_retry def create_test_issue(): return create_issue(CreateIssueParams( owner=owner, repo=repo, title=title )) issue = create_test_issue() try: # Verify no labels initially assert not issue["labels"], "Issue should not have labels initially" # Add labels @with_retry def add_test_labels(): return add_issue_labels(AddIssueLabelsParams( owner=owner, repo=repo, issue_number=issue["issue_number"], labels=["bug", "enhancement", "documentation"] )) labels = add_test_labels() # Verify labels were added assert len(labels) >= 3 label_names = [label["name"] for label in labels] assert "bug" in label_names assert "enhancement" in label_names assert "documentation" in label_names # Remove one label @with_retry def remove_bug_label(): return remove_issue_label(RemoveIssueLabelParams( owner=owner, repo=repo, issue_number=issue["issue_number"], label="bug" )) remove_bug_label() # Verify label was removed @with_retry def get_issue_after_remove(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"] )) # Using update with no changes to get current state issue_after_remove = get_issue_after_remove() label_names_after = [label["name"] for label in issue_after_remove["labels"]] assert "bug" not in label_names_after assert "enhancement" in label_names_after assert "documentation" in label_names_after # Remove another label @with_retry def remove_enhancement_label(): return remove_issue_label(RemoveIssueLabelParams( owner=owner, repo=repo, issue_number=issue["issue_number"], label="enhancement" )) remove_enhancement_label() # Verify second label was removed @with_retry def get_issue_after_second_remove(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"] )) issue_after_second_remove = get_issue_after_second_remove() label_names_after_second = [label["name"] for label in issue_after_second_remove["labels"]] assert "bug" not in label_names_after_second assert "enhancement" not in label_names_after_second assert "documentation" in label_names_after_second # Remove last label @with_retry def remove_documentation_label(): return remove_issue_label(RemoveIssueLabelParams( owner=owner, repo=repo, issue_number=issue["issue_number"], label="documentation" )) remove_documentation_label() # Verify all labels are removed @with_retry def get_issue_after_all_removed(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"] )) issue_after_all_removed = get_issue_after_all_removed() assert not issue_after_all_removed["labels"], "All labels should be removed" finally: # Cleanup try: @with_retry def close_issue(): return update_issue(UpdateIssueParams( owner=owner, repo=repo, issue_number=issue["issue_number"], state="closed" )) close_issue() except Exception as e: print(f"Failed to close issue during cleanup: {e}")

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/AstroMined/pygithub-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server