Build and Release Go-Easy #1
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: Build and Release Go-Easy | |
| on: | |
| schedule: | |
| # Check for updates daily at midnight UTC | |
| - cron: '0 0 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| force_build: | |
| description: 'Force build even if no changes are detected' | |
| type: boolean | |
| default: false | |
| version_suffix: | |
| description: 'Custom version suffix (default is -easy)' | |
| type: string | |
| default: '-easy' | |
| skip_release: | |
| description: 'Skip creating GitHub release' | |
| type: boolean | |
| default: false | |
| jobs: | |
| check-for-changes: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| has_changes: ${{ steps.check_changes.outputs.has_changes }} | |
| go_version: ${{ steps.extract_version.outputs.go_version }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 1 | |
| - name: Check repository structure | |
| run: | | |
| echo "Checking required files..." | |
| ls -R src/cmd/compile/internal/base/ | |
| ls -R src/cmd/compile/internal/types2/ | |
| ls -R src/cmd/dist/ | |
| shell: bash | |
| - name: Setup Go | |
| uses: actions/setup-go@v4 | |
| with: | |
| go-version: '1.20.15' # The latest in 1.20.x series required for building Go 1.22+ | |
| check-latest: true | |
| - name: Verify Go Version | |
| run: go version | |
| - name: Clone Go repository | |
| run: | | |
| git clone --depth=1 https://github.com/golang/go golang-repo | |
| cd golang-repo | |
| echo "GO_REPO_COMMIT=$(git rev-parse HEAD)" >> $GITHUB_ENV | |
| - name: Check if new changes exist in upstream | |
| id: check_changes | |
| run: | | |
| # If force_build is set to true, always build | |
| if [[ "${{ github.event.inputs.force_build }}" == "true" ]]; then | |
| echo "Force build requested, proceeding with build" | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| echo "$GO_REPO_COMMIT" > last_processed_commit.txt | |
| exit 0 | |
| fi | |
| # Check if we have a file that tracks the last processed commit | |
| if [ -f last_processed_commit.txt ]; then | |
| LAST_PROCESSED_COMMIT=$(cat last_processed_commit.txt) | |
| echo "Last processed commit: $LAST_PROCESSED_COMMIT" | |
| if [ "$LAST_PROCESSED_COMMIT" == "$GO_REPO_COMMIT" ]; then | |
| echo "No new changes in golang/go repository" | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "New changes detected in golang/go repository" | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| echo "$GO_REPO_COMMIT" > last_processed_commit.txt | |
| fi | |
| else | |
| echo "First time running workflow or tracking file not found" | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| echo "$GO_REPO_COMMIT" > last_processed_commit.txt | |
| fi | |
| - name: Extract Go version | |
| id: extract_version | |
| if: steps.check_changes.outputs.has_changes == 'true' | |
| run: | | |
| cd golang-repo | |
| # Check VERSION file first | |
| if [ -f VERSION ]; then | |
| GO_VERSION=$(cat VERSION | head -n 1) | |
| else | |
| # Extract version from src/internal/goversion/goversion.go if VERSION doesn't exist | |
| GOVERSION_SOURCE=$(cat src/internal/goversion/goversion.go) | |
| VERSION_NUM=$(echo "$GOVERSION_SOURCE" | grep -oP 'const Version = \K[0-9]+') | |
| GO_VERSION="go1.${VERSION_NUM}" | |
| # Check if this is a release branch | |
| if git branch -r | grep -q "release-branch.go1.${VERSION_NUM}"; then | |
| GO_VERSION="go1.${VERSION_NUM}" | |
| else | |
| # This is development, use full commit hash | |
| COMMIT_HASH=$(git rev-parse --short HEAD) | |
| COMMIT_DATE=$(git show -s --format=%ci HEAD | cut -d' ' -f1) | |
| GO_VERSION="devel ${GO_VERSION}-${COMMIT_HASH} ${COMMIT_DATE}" | |
| fi | |
| fi | |
| # Format the version string for the release name | |
| RELEASE_VERSION=$(echo "$GO_VERSION" | sed 's/^go//') | |
| echo "go_version=${RELEASE_VERSION}" >> $GITHUB_OUTPUT | |
| echo "Go version: ${GO_VERSION}" | |
| echo "Release version: ${RELEASE_VERSION}" | |
| - name: Save commit tracking file | |
| if: steps.check_changes.outputs.has_changes == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: commit-tracking | |
| path: last_processed_commit.txt | |
| build: | |
| needs: check-for-changes | |
| if: needs.check-for-changes.outputs.has_changes == 'true' | |
| strategy: | |
| matrix: | |
| include: | |
| # Linux builds | |
| - os: ubuntu-latest | |
| platform: linux | |
| arch: amd64 | |
| - os: ubuntu-latest | |
| platform: linux | |
| arch: 386 | |
| - os: ubuntu-latest | |
| platform: linux | |
| arch: arm64 | |
| - os: ubuntu-latest | |
| platform: linux | |
| arch: arm | |
| # macOS builds | |
| - os: macos-latest | |
| platform: darwin | |
| arch: amd64 | |
| - os: macos-latest | |
| platform: darwin | |
| arch: arm64 | |
| # Windows builds | |
| - os: windows-latest | |
| platform: windows | |
| arch: amd64 | |
| - os: windows-latest | |
| platform: windows | |
| arch: 386 | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup Go | |
| uses: actions/setup-go@v4 | |
| with: | |
| go-version: '1.20.15' # The latest in 1.20.x series required for building Go 1.22+ | |
| check-latest: true | |
| - name: Verify Go Version | |
| run: go version | |
| - name: Clone Go repository | |
| run: | | |
| git clone --depth=1 https://github.com/golang/go golang-repo | |
| - name: Download commit tracking file | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: commit-tracking | |
| - name: Apply Go-Easy changes (Unix) | |
| if: matrix.platform != 'windows' | |
| run: | | |
| # Apply our custom changes for Go-Easy | |
| cp -f src/cmd/compile/internal/base/print.go golang-repo/src/cmd/compile/internal/base/print.go | |
| cp -f src/cmd/compile/internal/types2/errors.go golang-repo/src/cmd/compile/internal/types2/errors.go | |
| cp -f src/cmd/compile/internal/types2/api.go golang-repo/src/cmd/compile/internal/types2/api.go | |
| cp -f src/cmd/dist/build.go golang-repo/src/cmd/dist/build.go | |
| # Create VERSION file with bootstrap version | |
| echo "go1.20.15" > golang-repo/VERSION | |
| echo "Created VERSION file with bootstrap version go1.20.15" | |
| # NOTE: Do not remove go.mod, go.sum, or go.work files – they are required for the build | |
| cd golang-repo | |
| echo "Set GOOS=${{ matrix.platform }} and GOARCH=${{ matrix.arch }}" | |
| - name: Apply Go-Easy changes (Windows) | |
| if: matrix.platform == 'windows' | |
| shell: pwsh | |
| run: | | |
| # Apply our custom changes for Go-Easy | |
| Copy-Item -Force src\cmd\compile\internal\base\print.go golang-repo\src\cmd\compile\internal\base\print.go | |
| Copy-Item -Force src\cmd\compile\internal\types2\errors.go golang-repo\src\cmd\compile\internal\types2\errors.go | |
| Copy-Item -Force src\cmd\compile\internal\types2\api.go golang-repo\src\cmd\compile\internal\types2\api.go | |
| Copy-Item -Force src\cmd\dist\build.go golang-repo\src\cmd\dist\build.go | |
| # Create VERSION file with bootstrap version | |
| Set-Content -Path "golang-repo\VERSION" -Value "go1.20.15" | |
| Write-Host "Created VERSION file with bootstrap version go1.20.15" | |
| # NOTE: Do not remove go.mod, go.sum, or go.work files | |
| cd golang-repo | |
| echo "Set GOOS=${{ matrix.platform }} and GOARCH=${{ matrix.arch }}" | |
| - name: Build Go for Linux/macOS | |
| if: matrix.platform != 'windows' | |
| run: | | |
| # Verify Go version first | |
| go version | |
| GOPATH=$(which go) | |
| GOROOT=$(dirname $(dirname $GOPATH)) | |
| echo "Go executable path: $GOPATH" | |
| echo "GOROOT: $GOROOT" | |
| # Set the bootstrap Go root – this is key according to the Go docs | |
| export GOROOT_BOOTSTRAP=$GOROOT | |
| echo "GOROOT_BOOTSTRAP: $GOROOT_BOOTSTRAP" | |
| cd golang-repo | |
| # Ensure the VERSION file is set | |
| echo "go1.20.15" > VERSION | |
| # Fix go.mod files to work with our bootstrap version if needed | |
| find . -name "go.mod" -exec sed -i.bak 's/go 1\.[2-9][0-9]/go 1.20/' {} \; | |
| find . -name "go.mod" -exec grep -l "go 1." {} \; | xargs -r cat | |
| echo "Modified go.mod files to ensure compatibility with Go 1.20 bootstrap" | |
| # Build Go using the official procedure | |
| cd src | |
| # Set cross-compilation environment variables | |
| export CGO_ENABLED=0 | |
| export GO111MODULE=off | |
| export GOTOOLCHAIN=local | |
| export GOOS=${{ matrix.platform }} | |
| export GOARCH=${{ matrix.arch }} | |
| echo "Environment variables:" | |
| echo "GOROOT_BOOTSTRAP: $GOROOT_BOOTSTRAP" | |
| echo "CGO_ENABLED: $CGO_ENABLED" | |
| echo "GO111MODULE: $GO111MODULE" | |
| echo "GOTOOLCHAIN: $GOTOOLCHAIN" | |
| echo "GOOS: $GOOS" | |
| echo "GOARCH: $GOARCH" | |
| ./make.bash | |
| - name: Build Go for Windows | |
| if: matrix.platform == 'windows' | |
| shell: pwsh | |
| run: | | |
| # Verify Go version first | |
| go version | |
| $goPath = (Get-Command go).Path | |
| $goRoot = (Split-Path -Parent (Split-Path -Parent $goPath)) | |
| Write-Host "Go executable path: $goPath" | |
| Write-Host "GOROOT: $goRoot" | |
| # Set the bootstrap Go root as required | |
| $env:GOROOT_BOOTSTRAP = $goRoot | |
| Write-Host "GOROOT_BOOTSTRAP: $env:GOROOT_BOOTSTRAP" | |
| cd golang-repo | |
| # Ensure the VERSION file is set | |
| Set-Content -Path "VERSION" -Value "go1.20.15" | |
| # Fix go.mod files to work with our bootstrap version if needed | |
| Get-ChildItem -Path . -Recurse -Filter "go.mod" | ForEach-Object { | |
| (Get-Content $_.FullName) -replace 'go 1\.[2-9][0-9]', 'go 1.20' | Set-Content $_.FullName | |
| Write-Host "Checking file: $($_.FullName)" | |
| Get-Content $_.FullName | Select-String "go 1." | |
| } | |
| Write-Host "Modified go.mod files to ensure compatibility with Go 1.20 bootstrap" | |
| # Build Go using the official documentation | |
| cd src | |
| # Set cross-compilation environment variables | |
| $env:CGO_ENABLED = "0" | |
| $env:GO111MODULE = "off" | |
| $env:GOTOOLCHAIN = "local" | |
| $env:GOOS = "${{ matrix.platform }}" | |
| $env:GOARCH = "${{ matrix.arch }}" | |
| Write-Host "Environment variables:" | |
| Write-Host "GOROOT_BOOTSTRAP: $env:GOROOT_BOOTSTRAP" | |
| Write-Host "CGO_ENABLED: $env:CGO_ENABLED" | |
| Write-Host "GO111MODULE: $env:GO111MODULE" | |
| Write-Host "GOTOOLCHAIN: $env:GOTOOLCHAIN" | |
| Write-Host "GOOS: $env:GOOS" | |
| Write-Host "GOARCH: $env:GOARCH" | |
| .\make.bat | |
| - name: Create package (Unix) | |
| if: matrix.platform != 'windows' | |
| run: | | |
| cd golang-repo | |
| # Create archive based on platform | |
| GO_VERSION="${{ needs.check-for-changes.outputs.go_version }}" | |
| VERSION_SUFFIX="${{ github.event.inputs.version_suffix || '-easy' }}" | |
| ARCHIVE_NAME="go${GO_VERSION}${VERSION_SUFFIX}-${{ matrix.platform }}-${{ matrix.arch }}" | |
| # Create a tar.gz archive for Linux/macOS | |
| tar -czf ${ARCHIVE_NAME}.tar.gz go | |
| echo "Created archive: ${ARCHIVE_NAME}.tar.gz" | |
| mkdir -p ../dist | |
| mv ${ARCHIVE_NAME}.tar.gz ../dist/ | |
| - name: Create package (Windows) | |
| if: matrix.platform == 'windows' | |
| shell: pwsh | |
| run: | | |
| cd golang-repo | |
| $GO_VERSION = "${{ needs.check-for-changes.outputs.go_version }}" | |
| $VERSION_SUFFIX = "${{ github.event.inputs.version_suffix || '-easy' }}" | |
| $ARCHIVE_NAME = "go${GO_VERSION}${VERSION_SUFFIX}-${{ matrix.platform }}-${{ matrix.arch }}" | |
| # Create a zip archive for Windows | |
| 7z a -tzip $ARCHIVE_NAME.zip go | |
| Write-Host "Created archive: $ARCHIVE_NAME.zip" | |
| New-Item -ItemType Directory -Force -Path ..\dist | |
| Move-Item $ARCHIVE_NAME.zip ..\dist\ | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: go-${{ matrix.platform }}-${{ matrix.arch }} | |
| path: dist/ | |
| retention-days: 1 | |
| release: | |
| needs: [check-for-changes, build] | |
| runs-on: ubuntu-latest | |
| if: needs.check-for-changes.outputs.has_changes == 'true' && github.event.inputs.skip_release != 'true' | |
| steps: | |
| - name: Download all build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ./artifacts | |
| - name: Prepare release files | |
| run: | | |
| mkdir -p ./release-files | |
| find ./artifacts -type f -not -path "*/commit-tracking/*" -exec cp {} ./release-files/ \; | |
| ls -la ./release-files/ | |
| - name: Create or update release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| name: "Go ${{ needs.check-for-changes.outputs.go_version }}${{ github.event.inputs.version_suffix || '-easy' }}" | |
| tag_name: "v${{ needs.check-for-changes.outputs.go_version }}${{ github.event.inputs.version_suffix || '-easy' }}" | |
| files: ./release-files/* | |
| draft: false | |
| prerelease: false | |
| fail_on_unmatched_files: false | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| generate_release_notes: true |