Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 172 additions & 0 deletions .github/workflows/parity-test-alicloud.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
name: '[Parity] AliCloud Output Comparison: TypeScript vs Python'

on:
workflow_dispatch:
inputs:
cidr:
description: 'VPC CIDR block'
required: false
default: '10.0.0.0/16'
subnets:
description: 'Number of vSwitches'
required: false
default: '4'
push:
branches:
- main
paths:
- 'src/templates/alicloud/**'
- 'skills/ipcalc-for-cloud/templates/alicloud/**'
- 'skills/ipcalc-for-cloud/scripts/template_processor.py'
- 'skills/ipcalc-for-cloud/scripts/cloud_provider_config.py'
- '.github/workflows/parity-test-alicloud.yml'
pull_request:
paths:
- 'src/templates/alicloud/**'
- 'skills/ipcalc-for-cloud/templates/alicloud/**'
- 'skills/ipcalc-for-cloud/scripts/template_processor.py'
- 'skills/ipcalc-for-cloud/scripts/cloud_provider_config.py'
- '.github/workflows/parity-test-alicloud.yml'

env:
VPC_CIDR: ${{ github.event.inputs.cidr || '10.0.0.0/16' }}
SUBNET_COUNT: ${{ github.event.inputs.subnets || '4' }}

jobs:
compare-alicloud-outputs:
name: Compare AliCloud outputs (TypeScript vs Python)
runs-on: ubuntu-latest

permissions:
contents: read

steps:
- name: Checkout code
uses: actions/checkout@v6

# ── TypeScript setup ────────────────────────────────────────────────────

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '24'
cache: 'npm'

- name: Install Node dependencies
run: npm ci

# ── Python setup ────────────────────────────────────────────────────────

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true

- name: Set up Python
run: uv python install 3.11

- name: Install Python dependencies
working-directory: skills/ipcalc-for-cloud
run: uv sync

# ── Generate outputs (single VPC) ───────────────────────────────────────

- name: Generate TypeScript outputs (single VPC)
run: |
mkdir -p /tmp/parity/single/ts /tmp/parity/single/py /tmp/parity/single/diff

for fmt in aliyun terraform; do
npm run cli -- \
--provider alicloud \
--cidr ${{ env.VPC_CIDR }} \
--subnets ${{ env.SUBNET_COUNT }} \
--output $fmt \
--file /tmp/parity/single/ts/${fmt}
echo "Generated TS single/$fmt"
done

- name: Generate Python outputs (single VPC)
working-directory: skills/ipcalc-for-cloud
run: |
for fmt in aliyun terraform; do
uv run python scripts/ipcalc.py \
--provider alicloud \
--cidr ${{ env.VPC_CIDR }} \
--subnets ${{ env.SUBNET_COUNT }} \
--output $fmt \
--file /tmp/parity/single/py/${fmt}
echo "Generated PY single/$fmt"
done

# ── Compare and report ──────────────────────────────────────────────────

- name: Compare outputs and generate report
id: compare
run: |
PASS=0
FAIL=0
REPORT_FILE=/tmp/parity-report.md

echo "## AliCloud Output Parity Report: TypeScript vs Python" > $REPORT_FILE
echo "" >> $REPORT_FILE
echo "**Date:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $REPORT_FILE
echo "**VPC CIDR:** \`${{ env.VPC_CIDR }}\` **vSwitches:** \`${{ env.SUBNET_COUNT }}\`" >> $REPORT_FILE
echo "" >> $REPORT_FILE

# ── Single VPC ──
echo "### Single VPC" >> $REPORT_FILE
echo "" >> $REPORT_FILE
echo "| Format | Result | Details |" >> $REPORT_FILE
echo "|--------|--------|---------|" >> $REPORT_FILE

for fmt in aliyun terraform; do
TS_FILE=/tmp/parity/single/ts/${fmt}
PY_FILE=/tmp/parity/single/py/${fmt}
DIFF_FILE=/tmp/parity/single/diff/${fmt}.diff

if diff "$TS_FILE" "$PY_FILE" > "$DIFF_FILE" 2>&1; then
echo "| \`$fmt\` | ✅ Identical | No differences |" >> $REPORT_FILE
PASS=$((PASS + 1))
else
LINES=$(wc -l < "$DIFF_FILE")
echo "| \`$fmt\` | ❌ Differs | $LINES diff lines — see artifact |" >> $REPORT_FILE
FAIL=$((FAIL + 1))
fi
done

echo "" >> $REPORT_FILE
echo "---" >> $REPORT_FILE
echo "**Total: $PASS passed, $FAIL failed** (out of $((PASS + FAIL)) comparisons)" >> $REPORT_FILE

cat $REPORT_FILE
cat $REPORT_FILE >> $GITHUB_STEP_SUMMARY

echo "pass=$PASS" >> $GITHUB_OUTPUT
echo "fail=$FAIL" >> $GITHUB_OUTPUT

- name: Show diffs for failing formats
if: steps.compare.outputs.fail != '0'
run: |
echo "=== Failing diffs ==="
for fmt in aliyun terraform; do
DIFF_FILE=/tmp/parity/single/diff/${fmt}.diff
if [ -s "$DIFF_FILE" ]; then
echo ""
echo "── single/$fmt ──────────────────────────"
cat "$DIFF_FILE"
fi
done

- name: Upload diff artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: alicloud-parity-diffs
path: /tmp/parity/single/
retention-days: 14

- name: Fail if any format differs
if: steps.compare.outputs.fail != '0'
run: |
echo "❌ ${{ steps.compare.outputs.fail }} format(s) differ between TypeScript and Python outputs."
exit 1
3 changes: 2 additions & 1 deletion skills/ipcalc-for-cloud/scripts/cloud_provider_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ class CloudProviderConfig(TypedDict):
'max_cidr_prefix': 8,
'min_cidr_prefix': 29,
'availability_zones': [
'cn-hangzhou-h', 'cn-hangzhou-i', 'cn-hangzhou-j', 'cn-hangzhou-k'
'cn-hangzhou-a', 'cn-hangzhou-b', 'cn-hangzhou-c',
'cn-hangzhou-d', 'cn-hangzhou-e', 'cn-hangzhou-f'
],
'supported_outputs': ['info', 'json', 'aliyun', 'terraform']
},
Expand Down
30 changes: 30 additions & 0 deletions skills/ipcalc-for-cloud/templates/alicloud/terraform.template.tf
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,31 @@ resource "alicloud_vpc" "vpc" {
# ========================================

{{vSwitchResources}}
# ========================================
# Security Group (Example)
# ========================================

resource "alicloud_security_group" "sg" {
security_group_name = "${var.vpc_name}-sg"
description = "Security group for ${var.vpc_name}"
vpc_id = alicloud_vpc.vpc.id

tags = {
Environment = "Production"
ManagedBy = "Terraform"
}
}

# Allow internal communication
resource "alicloud_security_group_rule" "allow_internal" {
type = "ingress"
ip_protocol = "all"
policy = "accept"
port_range = "-1/-1"
security_group_id = alicloud_security_group.sg.id
cidr_ip = var.vpc_cidr
}

# ========================================
# Outputs
# ========================================
Expand All @@ -80,4 +105,9 @@ output "vpc_cidr" {
value = alicloud_vpc.vpc.cidr_block
}

output "security_group_id" {
description = "ID of the Security Group"
value = alicloud_security_group.sg.id
}

{{vSwitchOutputs}}
Loading