{"id":49954367,"url":"https://github.com/tflynn3/gcdiff","last_synced_at":"2026-05-17T22:07:00.873Z","repository":{"id":321341156,"uuid":"1085457234","full_name":"tflynn3/gcdiff","owner":"tflynn3","description":"🔍 Compare and audit GCP resources across projects - perfect for Terraform validation and infrastructure auditing","archived":false,"fork":false,"pushed_at":"2025-10-29T05:47:54.000Z","size":40,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-29T06:22:18.853Z","etag":null,"topics":["audit","cli","cloud","comparison","devops","diff","gcp","golang","google-cloud","infrastructure","terraform"],"latest_commit_sha":null,"homepage":"https://github.com/tflynn3/gcdiff#readme","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tflynn3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-29T04:16:56.000Z","updated_at":"2025-10-29T05:47:52.000Z","dependencies_parsed_at":"2025-10-29T06:22:21.680Z","dependency_job_id":"c67a3ea8-daf4-4c57-84be-0d882396decf","html_url":"https://github.com/tflynn3/gcdiff","commit_stats":null,"previous_names":["tflynn3/gcdiff"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/tflynn3/gcdiff","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tflynn3%2Fgcdiff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tflynn3%2Fgcdiff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tflynn3%2Fgcdiff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tflynn3%2Fgcdiff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tflynn3","download_url":"https://codeload.github.com/tflynn3/gcdiff/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tflynn3%2Fgcdiff/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33157234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T09:28:26.183Z","status":"ssl_error","status_checked_at":"2026-05-17T09:27:52.702Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audit","cli","cloud","comparison","devops","diff","gcp","golang","google-cloud","infrastructure","terraform"],"created_at":"2026-05-17T22:06:47.209Z","updated_at":"2026-05-17T22:07:00.866Z","avatar_url":"https://github.com/tflynn3.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gcdiff\n\n[![Tests](https://github.com/tflynn3/gcdiff/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/tflynn3/gcdiff/actions/workflows/test.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/tflynn3/gcdiff)](https://goreportcard.com/report/github.com/tflynn3/gcdiff)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Release](https://img.shields.io/github/v/release/tflynn3/gcdiff)](https://github.com/tflynn3/gcdiff/releases)\n[![Homebrew](https://img.shields.io/badge/Homebrew-tflynn3%2Ftap%2Fgcdiff-orange)](https://github.com/tflynn3/homebrew-tap)\n\nA terminal tool for comparing and auditing GCP resources across projects.\n\n`gcdiff` helps you identify exact differences between GCP resources, making it especially useful for:\n- Validating Terraform configurations match live resources\n- Replicating environments across projects\n- Auditing infrastructure changes\n- Cross-project resource comparison\n\n## Features\n\n- **Dynamic resource support** - compare **ANY** GCP resource type without explicit code\n- **Deep comparison** of GCP resources with field-level granularity\n- **Git-style diff output** with color-coded changes\n- **Configurable field filtering** to ignore auto-generated or timestamp fields\n- **Uses gcloud auth** - leverages your existing authentication\n- **Cross-project support** - compare resources across different GCP projects\n- **Easy installation** via Homebrew\n\n### Instantly Supported Resources\n\nBecause gcdiff uses `gcloud` CLI under the hood, **all GCP resources are automatically supported**:\n- Compute Engine (instances, disks, snapshots, images, etc.)\n- Cloud Storage (buckets)\n- Networking (VPCs, subnets, firewalls, routes, load balancers)\n- Cloud Run (services, jobs)\n- Cloud SQL (instances, databases)\n- Pub/Sub (topics, subscriptions)\n- IAM (service accounts, roles)\n- GKE (clusters, node pools)\n- And literally **every other GCP resource** that gcloud supports!\n\n## Installation\n\n### Homebrew (macOS/Linux)\n\n```bash\nbrew install tflynn3/tap/gcdiff\n```\n\n### From source\n\n```bash\ngo install github.com/tflynn3/gcdiff/cmd/gcdiff@latest\n```\n\n### Binary releases\n\nDownload pre-built binaries from the [releases page](https://github.com/tflynn3/gcdiff/releases).\n\n## Quick Start\n\n### How It Works\n\nUse quoted gcloud resource paths that match the gcloud command structure:\n\n```bash\n# Format: gcdiff resource \"\u003cservice\u003e \u003cresource\u003e\" name-1 name-2 [flags]\n# Matches: gcloud \u003cservice\u003e \u003cresource\u003e describe \u003cname\u003e\n```\n\n### Examples\n\n```bash\n# Compute instances (from: gcloud compute instances describe)\ngcdiff resource \"compute instances\" instance-1 instance-2 \\\n  --project1=my-project \\\n  --zone1=us-central1-a\n\n# Firewall rules (from: gcloud compute firewall-rules describe)\ngcdiff resource \"compute firewall-rules\" rule-1 rule-2 \\\n  --project1=my-project\n\n# Storage buckets (from: gcloud storage buckets describe)\ngcdiff resource \"storage buckets\" bucket-1 bucket-2 \\\n  --project1=my-project\n\n# Cloud Run services (from: gcloud run services describe)\ngcdiff resource \"run services\" service-1 service-2 \\\n  --project1=my-project \\\n  --region1=us-central1\n\n# Pub/Sub topics (from: gcloud pubsub topics describe)\ngcdiff resource \"pubsub topics\" topic-1 topic-2 \\\n  --project1=my-project\n\n# Cloud SQL instances (from: gcloud sql instances describe)\ngcdiff resource \"sql instances\" instance-1 instance-2 \\\n  --project1=my-project\n\n# GKE clusters (from: gcloud container clusters describe)\ngcdiff resource \"container clusters\" cluster-1 cluster-2 \\\n  --project1=my-project \\\n  --zone1=us-central1-a\n```\n\n### Cross-Project Comparison\n```bash\n# Verify staging matches production\ngcdiff resource \"compute instances\" web-server web-server \\\n  --project1=my-prod-project \\\n  --project2=my-staging-project \\\n  --zone1=us-central1-a\n```\n\n### IAM Policy Comparison\n\nUse the `--iam` flag to include IAM bindings in your comparison. This works for ANY GCP resource that supports IAM policies:\n\n```bash\n# Compare Pub/Sub subscriptions including IAM bindings\ngcdiff resource \"pubsub subscriptions\" sub-1 sub-2 \\\n  --project1=my-project \\\n  --iam\n\n# Compare Cloud Run services including IAM bindings\ngcdiff resource \"run services\" service-1 service-2 \\\n  --project1=my-project \\\n  --region1=us-central1 \\\n  --iam\n\n# Compare storage buckets including IAM bindings\ngcdiff resource \"storage buckets\" bucket-1 bucket-2 \\\n  --project1=my-project \\\n  --iam\n```\n\nThe `--iam` flag fetches both:\n- Resource properties (configuration, metadata, etc.)\n- IAM policy bindings (roles and members)\n\nThis shows differences in resource configuration AND who has access to the resource in a single comparison.\n\n### Backward-Compatible Compute Command\n\nFor convenience, there's a shorthand for compute instances:\n\n```bash\ngcdiff compute instance-1 instance-2 \\\n  --project1=my-project \\\n  --zone1=us-central1-a\n```\n\n## Authentication\n\n`gcdiff` uses [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials). Make sure you're authenticated with gcloud:\n\n```bash\ngcloud auth application-default login\n```\n\n## Same-Project vs Cross-Project Comparisons\n\n`gcdiff` automatically adjusts its behavior based on comparison context:\n\n### Same-Project Comparison\nWhen comparing resources within the same project (default behavior), `gcdiff` automatically ignores:\n- Resource names (must be unique within a project)\n- Self-links (contain resource names)\n- Auto-generated IDs and timestamps\n\nThis is useful for comparing similar resources in the same environment.\n\n### Cross-Project Comparison\nWhen comparing resources across different projects (`--project1` ≠ `--project2`), `gcdiff` **includes** resource names and identifiers in the comparison. This is perfect for:\n- Validating that a resource in one project matches another project (same name, same config)\n- Terraform validation: ensuring your Terraform creates resources that match production\n- Environment parity checks: prod vs staging\n\nExample cross-project comparison:\n```bash\n# Verify staging instance matches prod configuration\ngcdiff compute web-server web-server \\\n  --project1=my-prod-project \\\n  --project2=my-staging-project \\\n  --zone1=us-central1-a\n```\n\nIf both instances are named \"web-server\" and have identical configurations, gcdiff will report no differences (except auto-generated fields like timestamps).\n\n## Configuration\n\nCreate a `.gcdiff.yaml` file in your home directory or current directory to customize behavior:\n\n```yaml\n# Default projects (optional - command-line flags override these)\nproject1: my-prod-project\nproject2: my-staging-project\n\n# Fields to ignore when comparing (exact matches)\nignore_fields:\n  - id\n  - selfLink\n  - creationTimestamp\n  - fingerprint\n  - kind\n  - etag\n\n# Regex patterns for fields to ignore\nignore_patterns:\n  - \".*Timestamp$\"\n  - \".*Fingerprint$\"\n```\n\n### Default Projects\n\nSetting `project1` and `project2` in your config file allows you to run commands without specifying `--project1` and `--project2` every time:\n\n```bash\n# Without config\ngcdiff resource firewall rule-1 rule-2 --project1=prod --project2=staging\n\n# With config file setting project1 and project2\ngcdiff resource firewall rule-1 rule-2\n\n# Override config with command-line flags\ngcdiff resource firewall rule-1 rule-2 --project1=different-project\n```\n\nYou can override the config location with `--config`:\n\n```bash\ngcdiff compute instance-1 instance-2 --config=/path/to/config.yaml\n```\n\n## Supported Resources\n\n**All GCP resources are supported dynamically!**\n\nThe tool uses `gcloud` CLI commands under the hood, which means any resource that gcloud can describe is automatically supported. No code changes needed to add support for new resource types!\n\nSimply use the gcloud resource path in quotes matching the command structure:\n- `gcloud \u003cservice\u003e \u003cresource\u003e describe` → `gcdiff resource \"\u003cservice\u003e \u003cresource\u003e\"`\n\n### More Examples\n\n```bash\n# GKE clusters (from: gcloud container clusters describe)\ngcdiff resource \"container clusters\" cluster-1 cluster-2 \\\n  --project1=my-project \\\n  --zone1=us-central1-a\n\n# Cloud Functions (from: gcloud functions describe)\ngcdiff resource \"functions\" function-1 function-2 \\\n  --project1=my-project \\\n  --region1=us-central1\n\n# IAM service accounts (from: gcloud iam service-accounts describe)\ngcdiff resource \"iam service-accounts\" sa-1 sa-2 \\\n  --project1=my-project\n\n# VPC networks (from: gcloud compute networks describe)\ngcdiff resource \"compute networks\" network-1 network-2 \\\n  --project1=my-project\n```\n\n## Example Output\n\n```\nComparing: prod-web \u003c-\u003e staging-web\n--------------------------------------------------------------------------------\n\nSummary: 3 difference(s) found\n  + 0 field(s)\n  - 0 field(s)\n  ~ 3 field(s)\n\nModified Fields:\n\n  ~ machineType\n      - \"n1-standard-2\"\n      + \"n1-standard-4\"\n\n  ~ disks[0].diskSizeGb\n      - 50\n      + 100\n\n  ~ networkInterfaces[0].accessConfigs[0].natIP\n      - \"35.123.45.67\"\n      + \"35.234.56.78\"\n```\n\n## Use Cases\n\n### Terraform Validation\n\nWhen replicating a GCP environment with Terraform:\n\n1. Deploy your Terraform configuration\n2. Use `gcdiff` to compare the Terraform-created resource with the original\n3. Identify any fields that don't match\n4. Adjust your Terraform config or use `--show-all` to see ignored fields\n\n```bash\ngcdiff compute terraform-instance original-instance \\\n  --project1=terraform-project \\\n  --project2=original-project \\\n  --zone1=us-central1-a\n```\n\n### Environment Replication Audit\n\nVerify that staging matches production:\n\n```bash\ngcdiff compute prod-app staging-app \\\n  --project1=prod \\\n  --project2=staging \\\n  --zone1=us-central1-a\n```\n\n## Development\n\n```bash\n# Clone the repo\ngit clone https://github.com/tflynn3/gcdiff.git\ncd gcdiff\n\n# Build\nmake build\n# or: go build -o gcdiff ./cmd/gcdiff\n\n# Run tests\nmake test\n\n# Run tests with coverage\nmake coverage\n\n# Format and lint\nmake fmt\nmake lint\n\n# Run all checks\nmake check\n\n# Run the binary\n./gcdiff --help\n```\n\n### Running Tests\n\nThe project has comprehensive unit tests with \u003e95% coverage for core logic:\n\n```bash\n# Run all tests\ngo test ./...\n\n# Run with coverage\ngo test -coverprofile=coverage.out ./...\ngo tool cover -html=coverage.out\n\n# Run with race detector\ngo test -race ./...\n```\n\nTest structure:\n- `internal/config/config_test.go` - Configuration loading and filtering tests\n- `internal/compare/differ_test.go` - Comparison logic tests\n- `internal/compare/output_test.go` - Output formatting tests\n- `internal/compare/integration_test.go` - End-to-end integration tests\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftflynn3%2Fgcdiff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftflynn3%2Fgcdiff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftflynn3%2Fgcdiff/lists"}