diff --git a/.github/workflows/pull-request-reporting-demo.yml b/.github/workflows/pull-request-reporting-demo.yml new file mode 100644 index 0000000..17595cb --- /dev/null +++ b/.github/workflows/pull-request-reporting-demo.yml @@ -0,0 +1,42 @@ +name: pull request reporting demo + +on: + pull_request: + types: [opened, reopened, synchronize] + +permissions: + contents: read + pull-requests: write + +jobs: + architecture-review: + name: architecture review + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Check out demo branch + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Prepare exact demo dialects + shell: bash + run: | + set -euo pipefail + for project in before current; do + mkdir -p "test/e2e/pull-request-reporting/${project}/.rootform" + cp -R \ + test/e2e/pull-request-reporting/dialects \ + "test/e2e/pull-request-reporting/${project}/.rootform/dialects" + done + + - name: Run Rootform architecture review + uses: ./ + with: + artifact-name: rootform-pr-${{ github.event.pull_request.number }} + baseline-path: test/e2e/pull-request-reporting/before + fail-on-changes: "false" + fail-on-violations: "true" + github-token: ${{ secrets.ROOTFORM_RELEASES_READ_TOKEN }} + path: test/e2e/pull-request-reporting/current + pull-request-token: ${{ github.token }} + report-diff: "true" + version: 0.1.0-dev.2 diff --git a/test/e2e/pull-request-reporting/before/main.tf b/test/e2e/pull-request-reporting/before/main.tf new file mode 100644 index 0000000..381bb2d --- /dev/null +++ b/test/e2e/pull-request-reporting/before/main.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">= 1.14.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "= 6.62.0" + } + } +} + +resource "aws_vpc" "main" { + cidr_block = "10.20.0.0/16" +} + +resource "aws_subnet" "application" { + vpc_id = aws_vpc.main.id + cidr_block = "10.20.1.0/24" +} diff --git a/test/e2e/pull-request-reporting/current/main.tf b/test/e2e/pull-request-reporting/current/main.tf new file mode 100644 index 0000000..381bb2d --- /dev/null +++ b/test/e2e/pull-request-reporting/current/main.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">= 1.14.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "= 6.62.0" + } + } +} + +resource "aws_vpc" "main" { + cidr_block = "10.20.0.0/16" +} + +resource "aws_subnet" "application" { + vpc_id = aws_vpc.main.id + cidr_block = "10.20.1.0/24" +} diff --git a/test/e2e/pull-request-reporting/dialects/aws/dialect.rf b/test/e2e/pull-request-reporting/dialects/aws/dialect.rf new file mode 100644 index 0000000..e4c7635 --- /dev/null +++ b/test/e2e/pull-request-reporting/dialects/aws/dialect.rf @@ -0,0 +1,11 @@ +dialect "aws" { + version = "0.1.0" + + requires { + core = "0.1.0" + } + + provider "hashicorp/aws" { + version = "= 6.62.0" + } +} diff --git a/test/e2e/pull-request-reporting/dialects/aws/network/ec2.rf b/test/e2e/pull-request-reporting/dialects/aws/network/ec2.rf new file mode 100644 index 0000000..a8db464 --- /dev/null +++ b/test/e2e/pull-request-reporting/dialects/aws/network/ec2.rf @@ -0,0 +1,198 @@ +# Generated by scripts/generate-aws-dialect.ts. +concept "customer-gateway" { + kind = entity + description = "AWS VPN (Site-to-Site) customer gateway as a durable AWS architecture entity." +} + +concept "ec2-client-vpn-endpoint" { + kind = entity + description = "AWS VPN (Client) client VPN endpoint as a durable AWS architecture entity." +} + +concept "ec2-transit-gateway-multicast-domain" { + kind = scope + description = "AWS Transit Gateway transit gateway multicast domain as a durable AWS architecture scope." +} + +concept "ec2-transit-gateway-policy-table" { + kind = entity + description = "AWS Transit Gateway transit gateway policy table as a durable AWS architecture entity." +} + +concept "ec2-transit-gateway-route-table" { + kind = entity + description = "AWS Transit Gateway transit gateway route table as a durable AWS architecture entity." +} + +concept "egress-only-internet-gateway" { + kind = entity + description = "Amazon VPC egress-only internet gateway as a durable AWS architecture entity." +} + +concept "internet-gateway" { + kind = entity + description = "Amazon VPC internet gateway as a durable AWS architecture entity." +} + +concept "network-acl" { + kind = entity + description = "Amazon VPC network ACL as a durable AWS architecture entity." +} + +concept "route-table" { + kind = entity + description = "Amazon VPC route table as a durable AWS architecture entity." +} + +concept "security-group" { + kind = entity + description = "Amazon VPC security group as a durable AWS architecture entity." +} + +concept "transit-gateway" { + kind = entity + description = "An AWS Transit Gateway connecting multiple networks." +} + +concept "transit-gateway-attachment" { + kind = detail + description = "A network attachment contributing to an AWS Transit Gateway." +} + +concept "verifiedaccess-endpoint" { + kind = entity + description = "AWS Verified Access verified access endpoint as a durable AWS architecture entity." +} + +concept "verifiedaccess-group" { + kind = entity + description = "AWS Verified Access verified access group as a durable AWS architecture entity." +} + +concept "verifiedaccess-instance" { + kind = entity + description = "AWS Verified Access verified access instance as a durable AWS architecture entity." +} + +concept "vpc-endpoint-service" { + kind = entity + description = "Amazon VPC VPC endpoint service as a durable AWS architecture entity." +} + +concept "vpc-ipam-pool" { + kind = scope + description = "AWS VPC IPAM (IP Address Manager) ipam pool as a durable AWS architecture scope." +} + +concept "vpc-route-server-endpoint" { + kind = entity + description = "Amazon VPC VPC route server endpoint as a durable AWS architecture entity." +} + +rule "customer-gateway" { + match { + kind = "resource" + type = "aws_customer_gateway" + } + + as = concept.customer-gateway +} + +rule "ec2-client-vpn-endpoint" { + match { + kind = "resource" + type = "aws_ec2_client_vpn_endpoint" + } + + as = concept.ec2-client-vpn-endpoint +} + +rule "ec2-transit-gateway-multicast-domain" { + match { + kind = "resource" + type = "aws_ec2_transit_gateway_multicast_domain" + } + + as = concept.ec2-transit-gateway-multicast-domain +} + +rule "ec2-transit-gateway-policy-table" { + match { + kind = "resource" + type = "aws_ec2_transit_gateway_policy_table" + } + + as = concept.ec2-transit-gateway-policy-table +} + +rule "ec2-transit-gateway-route-table" { + match { + kind = "resource" + type = "aws_ec2_transit_gateway_route_table" + } + + as = concept.ec2-transit-gateway-route-table +} + +rule "egress-only-internet-gateway" { + match { + kind = "resource" + type = "aws_egress_only_internet_gateway" + } + + as = concept.egress-only-internet-gateway +} + +rule "verifiedaccess-endpoint" { + match { + kind = "resource" + type = "aws_verifiedaccess_endpoint" + } + + as = concept.verifiedaccess-endpoint +} + +rule "verifiedaccess-group" { + match { + kind = "resource" + type = "aws_verifiedaccess_group" + } + + as = concept.verifiedaccess-group +} + +rule "verifiedaccess-instance" { + match { + kind = "resource" + type = "aws_verifiedaccess_instance" + } + + as = concept.verifiedaccess-instance +} + +rule "vpc-endpoint-service" { + match { + kind = "resource" + type = "aws_vpc_endpoint_service" + } + + as = concept.vpc-endpoint-service +} + +rule "vpc-ipam-pool" { + match { + kind = "resource" + type = "aws_vpc_ipam_pool" + } + + as = concept.vpc-ipam-pool +} + +rule "vpc-route-server-endpoint" { + match { + kind = "resource" + type = "aws_vpc_route_server_endpoint" + } + + as = concept.vpc-route-server-endpoint +} diff --git a/test/e2e/pull-request-reporting/dialects/aws/network/vpc.rf b/test/e2e/pull-request-reporting/dialects/aws/network/vpc.rf new file mode 100644 index 0000000..bdd5c50 --- /dev/null +++ b/test/e2e/pull-request-reporting/dialects/aws/network/vpc.rf @@ -0,0 +1,187 @@ +rule "vpc" { + match { + kind = "resource" + type = "aws_vpc" + } + + as = concept.core.virtual-network +} + +rule "subnet" { + match { + kind = "resource" + type = "aws_subnet" + } + + as = concept.core.subnet + + context { + as = context.core.network + to = concept.core.virtual-network + via = source.vpc_id + } +} + +rule "vpc-endpoint" { + match { + kind = "resource" + type = "aws_vpc_endpoint" + } + + as = concept.core.private-endpoint + + context { + as = context.core.network + to = concept.core.virtual-network + via = source.vpc_id + } +} + +rule "ec2-transit-gateway" { + match { + kind = "resource" + type = "aws_ec2_transit_gateway" + } + + as = concept.transit-gateway +} + +rule "ec2-transit-gateway-vpc-attachment" { + match { + kind = "resource" + type = "aws_ec2_transit_gateway_vpc_attachment" + } + + as = concept.transit-gateway-attachment + + contribution { + to = concept.transit-gateway + via = source.transit_gateway_id + } + + context { + as = context.core.network + to = concept.core.virtual-network + via = source.vpc_id + } +} + +rule "route-table" { + match { + kind = "resource" + type = "aws_route_table" + } + + as = concept.route-table + + context { + as = context.core.network + to = concept.core.virtual-network + via = source.vpc_id + } +} + +rule "security-group" { + match { + kind = "resource" + type = "aws_security_group" + } + + as = concept.security-group + + context { + as = context.core.network + to = concept.core.virtual-network + via = source.vpc_id + } +} + +rule "network-acl" { + match { + kind = "resource" + type = "aws_network_acl" + } + + as = concept.network-acl + + context { + as = context.core.network + to = concept.core.virtual-network + via = source.vpc_id + } +} + +rule "internet-gateway" { + match { + kind = "resource" + type = "aws_internet_gateway" + } + + as = concept.internet-gateway + + context { + as = context.core.network + to = concept.core.virtual-network + via = source.vpc_id + } +} + +rule "nat-gateway" { + match { + kind = "resource" + type = "aws_nat_gateway" + } + + as = concept.core.managed-nat + + context { + as = context.core.network + to = concept.core.subnet + via = source.subnet_id + } +} + +rule "vpn-gateway" { + match { + kind = "resource" + type = "aws_vpn_gateway" + } + + as = concept.core.vpn-gateway + + context { + as = context.core.network + to = concept.core.virtual-network + via = source.vpc_id + } +} + +rule "vpc-peering-connection" { + match { + kind = "resource" + type = "aws_vpc_peering_connection" + } + + as = concept.core.network-peering +} + +rule "vpn-connection" { + match { + kind = "resource" + type = "aws_vpn_connection" + } + + as = concept.core.vpn-connection + + context { + as = context.core.network + to = concept.core.vpn-gateway + via = source.vpn_gateway_id + } + + context { + as = context.core.network + to = concept.transit-gateway + via = source.transit_gateway_id + } +} diff --git a/test/e2e/pull-request-reporting/dialects/core/architecture/contexts.rf b/test/e2e/pull-request-reporting/dialects/core/architecture/contexts.rf new file mode 100644 index 0000000..b36e680 --- /dev/null +++ b/test/e2e/pull-request-reporting/dialects/core/architecture/contexts.rf @@ -0,0 +1,15 @@ +context "network" { + description = "Network placement or containment." +} + +context "runtime" { + description = "Runtime placement or execution scope." +} + +context "ownership" { + description = "Administrative or lifecycle ownership." +} + +context "geography" { + description = "Geographic placement." +} diff --git a/test/e2e/pull-request-reporting/dialects/core/dialect.rf b/test/e2e/pull-request-reporting/dialects/core/dialect.rf new file mode 100644 index 0000000..e49fa84 --- /dev/null +++ b/test/e2e/pull-request-reporting/dialects/core/dialect.rf @@ -0,0 +1,3 @@ +dialect "core" { + version = "0.1.0" +} diff --git a/test/e2e/pull-request-reporting/dialects/core/network/connectivity.rf b/test/e2e/pull-request-reporting/dialects/core/network/connectivity.rf new file mode 100644 index 0000000..0de3cd1 --- /dev/null +++ b/test/e2e/pull-request-reporting/dialects/core/network/connectivity.rf @@ -0,0 +1,24 @@ +concept "managed-nat" { + kind = entity + description = "A managed network address translation service." +} + +concept "network-peering" { + kind = entity + description = "A direct private connectivity agreement between virtual networks." +} + +concept "private-endpoint" { + kind = entity + description = "A private endpoint exposing a service inside a virtual network." +} + +concept "vpn-gateway" { + kind = entity + description = "A managed gateway terminating virtual private network connections." +} + +concept "vpn-connection" { + kind = entity + description = "A virtual private network connection between network endpoints." +} diff --git a/test/e2e/pull-request-reporting/dialects/core/network/virtual-network.rf b/test/e2e/pull-request-reporting/dialects/core/network/virtual-network.rf new file mode 100644 index 0000000..ce73cd0 --- /dev/null +++ b/test/e2e/pull-request-reporting/dialects/core/network/virtual-network.rf @@ -0,0 +1,9 @@ +concept "virtual-network" { + kind = scope + description = "A virtual network that provides connectivity and isolation." +} + +concept "subnet" { + kind = scope + description = "A subnet that segments a virtual network." +}