feat: externalize packages for i18nify-go #150
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Auto-Generate Go Packages | |
| on: | |
| pull_request: | |
| types: [opened, synchronize] | |
| branches: | |
| - master | |
| paths: | |
| - 'i18nify-data/country/subdivisions/**' | |
| - 'i18nify-data/currency/**' | |
| - 'i18nify-data/bankcodes/**' | |
| - 'i18nify-data/country/metadata/**' | |
| - '!i18nify-data/go/**' | |
| push: | |
| branches: | |
| - master | |
| paths: | |
| - 'i18nify-data/country/subdivisions/**' | |
| - 'i18nify-data/currency/**' | |
| - 'i18nify-data/bankcodes/**' | |
| - 'i18nify-data/country/metadata/**' | |
| - '!i18nify-data/go/**' | |
| # Manual trigger via GitHub Actions UI | |
| workflow_dispatch: | |
| inputs: | |
| package: | |
| description: 'Package to generate' | |
| required: false | |
| type: choice | |
| default: 'all' | |
| options: | |
| - 'all' | |
| - 'country/subdivisions' | |
| - 'currency' | |
| - 'bankcodes' | |
| - 'country/metadata' | |
| branch: | |
| description: 'Branch to run on' | |
| required: true | |
| default: 'master' | |
| release: | |
| description: 'Create release version (only for master)' | |
| required: false | |
| type: boolean | |
| default: false | |
| concurrency: | |
| group: auto-generate-go-${{ github.event_name }}-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| # For PR/push: detect which packages have data changes | |
| detect-changes: | |
| name: Detect Data Changes | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' || github.event_name == 'push' | |
| outputs: | |
| packages: ${{ steps.filter.outputs.changes }} | |
| branch: ${{ github.event.pull_request.head.ref || github.ref_name }} | |
| pr_number: ${{ github.event.pull_request.number }} | |
| is_release: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: dorny/paths-filter@v3 | |
| id: filter | |
| with: | |
| base: ${{ github.event.pull_request.base.ref || github.event.before || 'HEAD~1' }} | |
| filters: | | |
| country/subdivisions: | |
| - 'i18nify-data/country/subdivisions/**' | |
| - '!i18nify-data/country/subdivisions/README.md' | |
| currency: | |
| - 'i18nify-data/currency/**' | |
| - '!i18nify-data/currency/README.md' | |
| bankcodes: | |
| - 'i18nify-data/bankcodes/**' | |
| - '!i18nify-data/bankcodes/README.md' | |
| country/metadata: | |
| - 'i18nify-data/country/metadata/**' | |
| - '!i18nify-data/country/metadata/README.md' | |
| # For workflow_dispatch: get inputs | |
| check-dispatch: | |
| name: Parse Manual Dispatch | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'workflow_dispatch' | |
| outputs: | |
| packages: ${{ steps.parse.outputs.packages }} | |
| branch: ${{ github.event.inputs.branch }} | |
| is_release: ${{ github.event.inputs.release == 'true' && github.event.inputs.branch == 'master' }} | |
| steps: | |
| - name: Parse inputs | |
| id: parse | |
| env: | |
| PACKAGE: ${{ github.event.inputs.package }} | |
| run: | | |
| if [ "$PACKAGE" != "all" ] && [ -n "$PACKAGE" ]; then | |
| echo "packages=[\"$PACKAGE\"]" >> $GITHUB_OUTPUT | |
| else | |
| echo 'packages=["country/subdivisions","currency","bankcodes","country/metadata"]' >> $GITHUB_OUTPUT | |
| fi | |
| # Generate packages | |
| generate: | |
| name: Generate ${{ matrix.package }} | |
| runs-on: ubuntu-latest | |
| needs: [detect-changes, check-dispatch] | |
| if: | | |
| always() && ( | |
| (needs.detect-changes.result == 'success' && needs.detect-changes.outputs.packages != '[]' && needs.detect-changes.outputs.packages != '') || | |
| (needs.check-dispatch.result == 'success') | |
| ) | |
| strategy: | |
| matrix: | |
| package: ${{ fromJson(needs.check-dispatch.outputs.packages || needs.detect-changes.outputs.packages || '[]') }} | |
| fail-fast: false | |
| outputs: | |
| released_packages: ${{ steps.release-tag.outputs.released_packages }} | |
| env: | |
| BRANCH: ${{ needs.check-dispatch.outputs.branch || needs.detect-changes.outputs.branch }} | |
| PR_NUMBER: ${{ needs.detect-changes.outputs.pr_number || '' }} | |
| IS_RELEASE: ${{ needs.check-dispatch.outputs.is_release || needs.detect-changes.outputs.is_release }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| ref: ${{ env.BRANCH }} | |
| - name: Check if proto exists | |
| id: check-proto | |
| run: | | |
| PROTO_DIR="i18nify-data/${{ matrix.package }}/proto" | |
| if [ -d "$PROTO_DIR" ] && ls "$PROTO_DIR"/*.proto 1> /dev/null 2>&1; then | |
| echo "has_proto=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has_proto=false" >> $GITHUB_OUTPUT | |
| echo "⚠️ No proto found for ${{ matrix.package }} - skipping" | |
| fi | |
| - name: Setup Go | |
| if: steps.check-proto.outputs.has_proto == 'true' | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.20' | |
| - name: Install protoc | |
| if: steps.check-proto.outputs.has_proto == 'true' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y protobuf-compiler jq | |
| go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.31.0 | |
| echo "$HOME/go/bin" >> $GITHUB_PATH | |
| - name: Validate package data | |
| if: steps.check-proto.outputs.has_proto == 'true' | |
| run: | | |
| chmod +x .github/scripts/go/validate-package.sh | |
| .github/scripts/go/validate-package.sh "${{ matrix.package }}" | |
| - name: Generate package | |
| if: steps.check-proto.outputs.has_proto == 'true' | |
| run: | | |
| chmod +x .github/scripts/go/generate-package.sh | |
| chmod +x .github/scripts/go/generate-test.sh | |
| .github/scripts/go/generate-package.sh "${{ matrix.package }}" | |
| - name: Verify package (run tests) | |
| if: steps.check-proto.outputs.has_proto == 'true' | |
| run: | | |
| cd "i18nify-data/go/${{ matrix.package }}" | |
| echo "Running tests to verify data loads correctly..." | |
| go test -v ./... | |
| echo "✅ All tests passed - data is valid and loadable" | |
| - name: Commit and push generated package | |
| if: steps.check-proto.outputs.has_proto == 'true' | |
| run: | | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| git add "i18nify-data/go/${{ matrix.package }}" | |
| if git diff --cached --quiet; then | |
| echo "No changes to commit" | |
| else | |
| git commit -m "chore: auto-regenerate ${{ matrix.package }} Go package" | |
| git pull --rebase origin "$BRANCH" || true | |
| git push origin HEAD:"$BRANCH" | |
| fi | |
| - name: Generate version | |
| if: steps.check-proto.outputs.has_proto == 'true' | |
| id: version | |
| run: | | |
| PACKAGE="${{ matrix.package }}" | |
| # Convert package path to tag prefix (e.g., country/subdivisions -> country-subdivisions) | |
| TAG_PREFIX=$(echo "$PACKAGE" | tr '/' '-') | |
| if [ "$IS_RELEASE" == "true" ]; then | |
| # For release: get latest tag and bump version | |
| git fetch --tags origin | |
| LATEST_TAG=$(git tag -l "${TAG_PREFIX}/v*" --sort=-version:refname | head -n 1 || echo "") | |
| if [ -z "$LATEST_TAG" ]; then | |
| # No existing tag, start at v1.0.0 | |
| NEW_VERSION="1.0.0" | |
| else | |
| # Extract version and bump patch | |
| CURRENT_VERSION=$(echo "$LATEST_TAG" | sed "s|${TAG_PREFIX}/v||") | |
| IFS='.' read -ra VERSION_PARTS <<< "$CURRENT_VERSION" | |
| MAJOR="${VERSION_PARTS[0]}" | |
| MINOR="${VERSION_PARTS[1]}" | |
| PATCH="${VERSION_PARTS[2]:-0}" | |
| NEW_PATCH=$((PATCH + 1)) | |
| NEW_VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}" | |
| fi | |
| echo "version=v${NEW_VERSION}" >> $GITHUB_OUTPUT | |
| echo "tag=${TAG_PREFIX}/v${NEW_VERSION}" >> $GITHUB_OUTPUT | |
| echo "is_release=true" >> $GITHUB_OUTPUT | |
| else | |
| # For PR/non-release: use pseudo-version | |
| COMMIT_SHA=$(git rev-parse HEAD) | |
| SHORT_SHA=$(echo "$COMMIT_SHA" | cut -c1-12) | |
| TIMESTAMP=$(TZ=UTC git show -s --format=%cd --date=format-local:%Y%m%d%H%M%S "$COMMIT_SHA") | |
| VERSION="v0.0.0-${TIMESTAMP}-${SHORT_SHA}" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "tag=" >> $GITHUB_OUTPUT | |
| echo "is_release=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Update go.mod dependencies | |
| if: steps.check-proto.outputs.has_proto == 'true' | |
| run: | | |
| chmod +x .github/scripts/go/update-dependencies.sh | |
| .github/scripts/go/update-dependencies.sh "${{ matrix.package }}" "${{ steps.version.outputs.version }}" | |
| - name: Commit and push go.mod | |
| if: steps.check-proto.outputs.has_proto == 'true' | |
| run: | | |
| git add packages/i18nify-go/go.mod packages/i18nify-go/go.sum | |
| if git diff --cached --quiet; then | |
| echo "No go.mod changes" | |
| exit 0 | |
| fi | |
| git commit -m "chore(go): update ${{ matrix.package }} to ${{ steps.version.outputs.version }}" | |
| git pull --rebase origin "$BRANCH" || true | |
| git push origin HEAD:"$BRANCH" | |
| - name: Create and push release tag | |
| if: steps.check-proto.outputs.has_proto == 'true' && steps.version.outputs.is_release == 'true' | |
| id: release-tag | |
| run: | | |
| TAG="${{ steps.version.outputs.tag }}" | |
| PACKAGE="${{ matrix.package }}" | |
| git tag -a "$TAG" -m "Release $PACKAGE ${{ steps.version.outputs.version }}" | |
| git push origin "$TAG" | |
| echo "Released $PACKAGE with tag $TAG" | |
| echo "released_packages=${PACKAGE}:${{ steps.version.outputs.version }}" >> $GITHUB_OUTPUT | |
| - name: Comment on PR | |
| if: steps.check-proto.outputs.has_proto == 'true' && env.PR_NUMBER != '' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| MODULE="github.com/razorpay/i18nify/i18nify-data/go/${{ matrix.package }}" | |
| gh pr comment "$PR_NUMBER" --body "## 📦 Package Updated | |
| **Package:** \`${{ matrix.package }}\` | |
| **Version:** \`$VERSION\` | |
| \`\`\`bash | |
| go get ${MODULE}@${VERSION} | |
| \`\`\`" | |
| # Release i18nify-go with updated dependencies (only on master push) | |
| release-i18nify-go: | |
| name: Release i18nify-go | |
| runs-on: ubuntu-latest | |
| needs: [detect-changes, generate] | |
| if: | | |
| always() && | |
| needs.detect-changes.outputs.is_release == 'true' && | |
| needs.generate.result == 'success' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.20' | |
| - name: Pull latest changes | |
| run: | | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| git pull origin master | |
| - name: Update dependencies to release versions | |
| id: update-deps | |
| env: | |
| PACKAGES: ${{ needs.detect-changes.outputs.packages }} | |
| run: | | |
| cd packages/i18nify-go | |
| # Get list of changed packages | |
| PACKAGE_LIST=$(echo "$PACKAGES" | jq -r '.[]' 2>/dev/null || echo "") | |
| if [ -z "$PACKAGE_LIST" ]; then | |
| echo "No packages to update" | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| # Fetch tags to get latest versions | |
| git fetch --tags origin | |
| for pkg in $PACKAGE_LIST; do | |
| # Convert package path to tag prefix | |
| TAG_PREFIX=$(echo "$pkg" | tr '/' '-') | |
| # Get latest tag for this package | |
| LATEST_TAG=$(git tag -l "${TAG_PREFIX}/v*" --sort=-version:refname | head -n 1 || echo "") | |
| if [ -z "$LATEST_TAG" ]; then | |
| echo "No release tag found for $pkg, skipping" | |
| continue | |
| fi | |
| # Extract version from tag | |
| VERSION=$(echo "$LATEST_TAG" | sed "s|${TAG_PREFIX}/v||") | |
| # Module path uses forward slashes | |
| MODULE_PATH="github.com/razorpay/i18nify/i18nify-data/go/${pkg}" | |
| # Check if module is in go.mod | |
| if ! grep -q "$MODULE_PATH" go.mod; then | |
| echo "Module $MODULE_PATH not found in go.mod, skipping" | |
| continue | |
| fi | |
| # Remove any replace directive | |
| if grep -q "replace ${MODULE_PATH}" go.mod; then | |
| go mod edit -dropreplace "${MODULE_PATH}" | |
| fi | |
| # Update to release version | |
| echo "Updating $MODULE_PATH to v${VERSION}" | |
| go mod edit -require "${MODULE_PATH}@v${VERSION}" | |
| done | |
| go mod tidy | |
| cd ../.. | |
| if [ -n "$(git status --porcelain packages/i18nify-go/go.mod packages/i18nify-go/go.sum)" ]; then | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Get current i18nify-go version | |
| if: steps.update-deps.outputs.has_changes == 'true' | |
| id: current-version | |
| run: | | |
| git fetch --tags origin | |
| # Look for i18nify-go tags (format: i18nify-go/vX.Y.Z) | |
| LATEST_TAG=$(git tag -l "i18nify-go/v*" --sort=-version:refname | head -n 1 || echo "") | |
| if [ -z "$LATEST_TAG" ]; then | |
| echo "version=0.0.0" >> $GITHUB_OUTPUT | |
| else | |
| VERSION=$(echo "$LATEST_TAG" | sed 's|i18nify-go/v||') | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Bump i18nify-go version | |
| if: steps.update-deps.outputs.has_changes == 'true' | |
| id: new-version | |
| env: | |
| CURRENT_VERSION: ${{ steps.current-version.outputs.version }} | |
| run: | | |
| # Parse version (semver: major.minor.patch) | |
| IFS='.' read -ra VERSION_PARTS <<< "$CURRENT_VERSION" | |
| MAJOR="${VERSION_PARTS[0]}" | |
| MINOR="${VERSION_PARTS[1]}" | |
| PATCH="${VERSION_PARTS[2]:-0}" | |
| # Bump minor version, reset patch | |
| NEW_MINOR=$((MINOR + 1)) | |
| NEW_VERSION="${MAJOR}.${NEW_MINOR}.0" | |
| echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT | |
| echo "Bumping i18nify-go from v${CURRENT_VERSION} to v${NEW_VERSION}" | |
| - name: Commit and tag i18nify-go release | |
| if: steps.update-deps.outputs.has_changes == 'true' | |
| env: | |
| NEW_VERSION: ${{ steps.new-version.outputs.version }} | |
| PACKAGES: ${{ needs.detect-changes.outputs.packages }} | |
| run: | | |
| # Get package list for commit message | |
| PACKAGE_LIST=$(echo "$PACKAGES" | jq -r 'join(", ")' 2>/dev/null || echo "updated packages") | |
| git add packages/i18nify-go/go.mod packages/i18nify-go/go.sum | |
| git commit -m "release(i18nify-go): v${NEW_VERSION}" \ | |
| -m "Updated dependencies: ${PACKAGE_LIST}" \ | |
| -m "Auto-released by GitHub Actions" | |
| # Create release tag | |
| NEW_TAG="i18nify-go/v${NEW_VERSION}" | |
| git tag -a "$NEW_TAG" -m "Release i18nify-go v${NEW_VERSION}" | |
| # Push commit and tag | |
| git push origin master | |
| git push origin "$NEW_TAG" | |
| echo "Released i18nify-go v${NEW_VERSION} with tag $NEW_TAG" |