diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 000000000..e63ac8924 --- /dev/null +++ b/.bazelrc @@ -0,0 +1,3 @@ +# Fix ccache issues in sandbox by using local strategy +# This prevents "Read-only file system" errors when ccache tries to write temp files +build --spawn_strategy=local diff --git a/.bcr/metadata.template.json b/.bcr/metadata.template.json new file mode 100644 index 000000000..34ee960c1 --- /dev/null +++ b/.bcr/metadata.template.json @@ -0,0 +1,13 @@ +{ + "homepage": "https://github.com/MrAMS/iverilog", + "maintainers": [ + { + "email": "", + "github": "MrAMS", + "name": "Qijia Yang" + } + ], + "repository": ["github:MrAMS/iverilog"], + "versions": [], + "yanked_versions": {} +} diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml new file mode 100644 index 000000000..c3e71a7f0 --- /dev/null +++ b/.bcr/presubmit.yml @@ -0,0 +1,23 @@ +# BCR presubmit configuration for iverilog module +# This file defines the build verification tests + +# Simple smoke test matrix +matrix: + platform: + - ubuntu2004 + bazel: ["7.x", "8.x"] + +tasks: + verify_targets: + name: Verify build targets + platform: ${{ platform }} + bazel: ${{ bazel }} + build_targets: + - "@iverilog//:iverilog" + - "@iverilog//:vvp" + - "@iverilog//:ivl" + - "@iverilog//:ivlpp" + - "@iverilog//:iverilog-bin" + - "@iverilog//:vvp-bin" + test_targets: + - "@iverilog//:hello_verilog_test" diff --git a/.bcr/source.template.json b/.bcr/source.template.json new file mode 100644 index 000000000..5d3774216 --- /dev/null +++ b/.bcr/source.template.json @@ -0,0 +1,5 @@ +{ + "integrity": "", + "strip_prefix": "iverilog-{VERSION}", + "url": "https://github.com/{OWNER}/{REPO}/releases/download/v{VERSION}/iverilog-{VERSION}.tar.gz" +} diff --git a/.github/bcr-config.yml b/.github/bcr-config.yml new file mode 100644 index 000000000..8fd66fd97 --- /dev/null +++ b/.github/bcr-config.yml @@ -0,0 +1,34 @@ +# This file contains the centralized configuration for all BCR-related workflows. +# All GitHub Actions workflows will read from this file. +# +# To change configuration, edit the values below and commit the changes. + +# Project name (used in archive naming) +project_name: iverilog + +# BCR registry fork repository +# This is where the module will be published +bcr_registry_fork: MrAMS/bazel-central-registry + +# Upstream repository +# Auto-detected from fork parent via GitHub API +# No manual configuration needed +upstream_url: auto-detected + +# Release archive excludes +# These files/directories are removed from release archives +exclude_from_archive: + - .git + - .github + - bazel-* + - scripts + - .gitmodules + - .gitignore + +# Sync schedule +# Monthly sync on the 1st day at 00:00 UTC +sync_schedule: "0 0 1 * *" +# Usage in workflows: +# - publish-to-bcr.yml: Reads project_name and bcr_registry_fork using yq +# - schedule-sync.yml: Uses sync_schedule and auto-detects upstream_url +# - All values are loaded dynamically at runtime diff --git a/.github/workflows/publish-to-bcr.yml b/.github/workflows/publish-to-bcr.yml new file mode 100644 index 000000000..25b83754d --- /dev/null +++ b/.github/workflows/publish-to-bcr.yml @@ -0,0 +1,103 @@ +name: Publish to BCR + +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag_name: + description: "Tag name to publish (e.g., v1.0.0)" + required: true + type: string + +jobs: + create-archive: + runs-on: ubuntu-latest + permissions: + contents: write + outputs: + tag_name: ${{ steps.get_version.outputs.tag_name }} + project_name: ${{ steps.load_config.outputs.project_name }} + bcr_registry_fork: ${{ steps.load_config.outputs.bcr_registry_fork }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.release.tag_name || inputs.tag_name }} + submodules: recursive + + - name: Load configuration + id: load_config + run: | + PROJECT_NAME=$(yq '.project_name' .github/bcr-config.yml) + BCR_REGISTRY_FORK=$(yq '.bcr_registry_fork' .github/bcr-config.yml) + + echo "project_name=$PROJECT_NAME" >> $GITHUB_OUTPUT + echo "bcr_registry_fork=$BCR_REGISTRY_FORK" >> $GITHUB_OUTPUT + + echo "Loaded configuration:" + echo " PROJECT_NAME=$PROJECT_NAME" + echo " BCR_REGISTRY_FORK=$BCR_REGISTRY_FORK" + + - name: Get version from tag + id: get_version + run: | + TAG_NAME="${{ github.event.release.tag_name || inputs.tag_name }}" + VERSION="${TAG_NAME#v}" + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "tag_name=${TAG_NAME}" >> $GITHUB_OUTPUT + echo "Version: ${VERSION}" + echo "Tag: ${TAG_NAME}" + + - name: Create release archive + run: | + PROJECT_NAME="${{ steps.load_config.outputs.project_name }}" + VERSION="${{ steps.get_version.outputs.version }}" + ARCHIVE_NAME="${PROJECT_NAME}-${VERSION}.tar.gz" + + echo "Creating archive: ${ARCHIVE_NAME}" + + # Create temporary directory with proper structure + mkdir -p /tmp/archive + cp -r . "/tmp/archive/${PROJECT_NAME}-${VERSION}/" + + # Remove unwanted files from archive + cd "/tmp/archive/${PROJECT_NAME}-${VERSION}" + rm -rf .git .github bazel-* scripts .gitmodules .gitignore + + # Create tar.gz archive + cd /tmp/archive + tar -czf "${ARCHIVE_NAME}" "${PROJECT_NAME}-${VERSION}/" + mv "${ARCHIVE_NAME}" "${GITHUB_WORKSPACE}/" + + echo "Archive created: ${ARCHIVE_NAME}" + ls -lh "${GITHUB_WORKSPACE}/${ARCHIVE_NAME}" + + - name: Upload release archive + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PROJECT_NAME="${{ steps.load_config.outputs.project_name }}" + TAG_NAME="${{ steps.get_version.outputs.tag_name }}" + VERSION="${{ steps.get_version.outputs.version }}" + ARCHIVE_NAME="${PROJECT_NAME}-${VERSION}.tar.gz" + + echo "Uploading ${ARCHIVE_NAME} to release ${TAG_NAME}..." + + gh release upload "${TAG_NAME}" "${ARCHIVE_NAME}" \ + --repo "${{ github.repository }}" \ + --clobber + + echo "Upload completed successfully" + + publish: + needs: create-archive + permissions: + contents: write + uses: bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@v1.0.0 + with: + tag_name: ${{ needs.create-archive.outputs.tag_name }} + registry_fork: ${{ needs.create-archive.outputs.bcr_registry_fork }} + attest: false + secrets: + publish_token: ${{ secrets.CI_PAT_TOKEN }} diff --git a/.github/workflows/schedule-sync.yml b/.github/workflows/schedule-sync.yml new file mode 100644 index 000000000..9735734f4 --- /dev/null +++ b/.github/workflows/schedule-sync.yml @@ -0,0 +1,150 @@ +name: Monthly Sync + +on: + schedule: + - cron: "0 0 1 * *" # Monthly on the 1st at 00:00 UTC + workflow_dispatch: + inputs: + force_release: + description: "Force release even if no changes?" + type: boolean + default: false + +env: + UPSTREAM_BRANCH: main # Will auto-detect if upstream uses 'master' instead + +jobs: + sync-and-release: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.CI_PAT_TOKEN }} + + - name: Get upstream URL from fork parent + id: get-upstream + run: | + # Get parent repository URL from GitHub API + UPSTREAM_URL=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/${{ github.repository }}" | \ + jq -r '.parent.html_url') + + if [ -z "$UPSTREAM_URL" ] || [ "$UPSTREAM_URL" = "null" ]; then + echo "Error: Could not get upstream URL. Is this repository a fork?" + exit 1 + fi + + echo "Upstream URL: $UPSTREAM_URL" + echo "upstream_url=$UPSTREAM_URL" >> $GITHUB_OUTPUT + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Detect upstream default branch + id: detect-branch + run: | + UPSTREAM_URL="${{ steps.get-upstream.outputs.upstream_url }}" + + # Add upstream remote + git remote add upstream "$UPSTREAM_URL" + git fetch upstream + + # Try to detect default branch + UPSTREAM_BRANCH=$(git remote show upstream | grep 'HEAD branch' | cut -d' ' -f5) + + if [ -z "$UPSTREAM_BRANCH" ]; then + # Fallback to env default + UPSTREAM_BRANCH="${{ env.UPSTREAM_BRANCH }}" + fi + + echo "Detected upstream branch: $UPSTREAM_BRANCH" + echo "branch=$UPSTREAM_BRANCH" >> $GITHUB_OUTPUT + + - name: Merge upstream changes + run: | + UPSTREAM_BRANCH="${{ steps.detect-branch.outputs.branch }}" + CURRENT_BRANCH=$(git branch --show-current) + + echo "Current branch: $CURRENT_BRANCH" + echo "Syncing from upstream branch: $UPSTREAM_BRANCH" + + # Merge upstream changes + git merge upstream/$UPSTREAM_BRANCH --no-edit || { + echo "Merge conflict detected. Manual intervention required." + exit 1 + } + + # Push merged changes to current branch + git push origin $CURRENT_BRANCH + + - name: Check changes and generate tag + id: check + run: | + # Get the last tag + LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + + # Get current and last tag commit hashes + CURRENT_HASH=$(git rev-parse HEAD) + if [ -n "$LAST_TAG" ]; then + LAST_TAG_HASH=$(git rev-parse "$LAST_TAG^{}") + else + LAST_TAG_HASH="" + fi + + echo "Last Tag: $LAST_TAG ($LAST_TAG_HASH)" + echo "Current: $CURRENT_HASH" + + # Skip if no changes and not forced + if [ "$CURRENT_HASH" == "$LAST_TAG_HASH" ] && [ "${{ inputs.force_release }}" != "true" ]; then + echo "No changes detected. Skipping release." + echo "release_needed=false" >> $GITHUB_OUTPUT + exit 0 + fi + + # Generate pseudo-version: v0.0.0-YYYYMMDD-commitHash + SHORT_HASH=$(git rev-parse --short=7 HEAD) + DATE_STR=$(date +'%Y%m%d') + NEW_TAG="v0.0.0-${DATE_STR}-${SHORT_HASH}" + + # Check if tag already exists + if git rev-parse "$NEW_TAG" >/dev/null 2>&1; then + echo "Tag $NEW_TAG already exists. Skipping." + echo "release_needed=false" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "New release will be: $NEW_TAG" + echo "release_needed=true" >> $GITHUB_OUTPUT + echo "new_tag=$NEW_TAG" >> $GITHUB_OUTPUT + + - name: Create GitHub release + if: steps.check.outputs.release_needed == 'true' + env: + GH_TOKEN: ${{ secrets.CI_PAT_TOKEN }} + run: | + TAG_NAME="${{ steps.check.outputs.new_tag }}" + UPSTREAM_URL="${{ steps.get-upstream.outputs.upstream_url }}" + + echo "Creating tag and release: $TAG_NAME" + + # Create and push tag + git tag "$TAG_NAME" + git push origin "$TAG_NAME" + + # Create GitHub release + COMMIT_HASH=$(git rev-parse HEAD) + RELEASE_NOTES="Synced with upstream $UPSTREAM_URL on $(date +'%Y-%m-%d'). + + Commit: $COMMIT_HASH" + + gh release create "$TAG_NAME" \ + --repo ${{ github.repository }} \ + --title "Auto Release $TAG_NAME" \ + --notes "$RELEASE_NOTES" \ + --generate-notes diff --git a/MODULE.bazel b/MODULE.bazel index 260927b0a..02afa2ef3 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,6 +1,6 @@ module( name = "iverilog", - version = "12.0.0", + version = "0.0.0", ) bazel_dep(name = "gperf", version = "3.1")