This is an automated email from the ASF dual-hosted git repository. sjanc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 3cc112b2717faca81b50fc76517539ec764680fb Author: Szymon Janc <[email protected]> AuthorDate: Tue Oct 13 17:34:24 2026 +0200 ci: Build newt once per workflow run Jobs not using project prepared by prepare job (prepare itself and Windows/macOS jobs) were building or restoring newt on their own, so newt could be built several times in parallel when cache was empty. Build newt for all platforms used by Build workflow in a single job and pass it to other jobs as artifact. Newt is cross-compiled, as it doesn't use cgo. Assisted-by: Claude:claude-opus-5-5 --- .github/actions/newt-install/action.yml | 112 ++++++++++++++++++++++++++++---- .github/workflows/build.yml | 30 +++++++++ .github/workflows/cache_cleanup.yml | 7 +- 3 files changed, 134 insertions(+), 15 deletions(-) diff --git a/.github/actions/newt-install/action.yml b/.github/actions/newt-install/action.yml index 58e406799..55e203bde 100644 --- a/.github/actions/newt-install/action.yml +++ b/.github/actions/newt-install/action.yml @@ -20,13 +20,70 @@ name: Install newt description: > Install newt built from master branch of apache/mynewt-newt. Built - binary is cached per newt commit, so newt is rebuilt only when newt - master branch changes. + binaries are cached per newt commit, so newt is rebuilt only when newt + master branch changes. Newt can also be taken from artifact uploaded + by another job of the same workflow run, so that it is built only once. + +inputs: + platforms: + description: > + Space separated list of GOOS/GOARCH platforms to build newt for, in + addition to platform of the runner. Binaries are stored in + directory provided by dist output. + required: false + default: '' + artifact: + description: > + Name of artifact with newt binaries (dist directory) uploaded by + another job. If set, newt is taken from it instead of being built. + required: false + default: '' + +outputs: + dist: + description: Directory with newt binaries, one subdirectory per platform + value: ${{ steps.platform.outputs.dist }} runs: using: composite steps: + - name: Get platforms + id: platform + shell: bash + env: + RUNNER_OS: ${{ runner.os }} + RUNNER_ARCH: ${{ runner.arch }} + PLATFORMS: ${{ inputs.platforms }} + run: | + case "$RUNNER_OS" in + Linux) goos=linux ;; + Windows) goos=windows ;; + macOS) goos=darwin ;; + esac + case "$RUNNER_ARCH" in + X64) goarch=amd64 ;; + ARM64) goarch=arm64 ;; + esac + if [ -z "$goos" ] || [ -z "$goarch" ]; then + echo "::error::Unsupported runner $RUNNER_OS $RUNNER_ARCH" + exit 1 + fi + host="$goos/$goarch" + all=$(echo "$host $PLATFORMS" | tr ' ' '\n' | grep . | sort -u | tr '\n' ' ') + echo "host=$host" >> "$GITHUB_OUTPUT" + echo "all=${all% }" >> "$GITHUB_OUTPUT" + # Relative to workspace, to avoid Windows paths in bash steps + echo "dist=.newt-dist" >> "$GITHUB_OUTPUT" + + - name: Download newt + if: inputs.artifact != '' + uses: actions/download-artifact@v8 + with: + name: ${{ inputs.artifact }} + path: ${{ steps.platform.outputs.dist }} + - name: Get newt master commit + if: inputs.artifact == '' id: newt shell: bash run: | @@ -37,15 +94,18 @@ runs: fi echo "newt master is at $sha" echo "sha=$sha" >> "$GITHUB_OUTPUT" + echo "platforms=$(echo ${{ steps.platform.outputs.all }} | tr '/ ' '_-')" >> "$GITHUB_OUTPUT" - name: Restore newt from cache + if: inputs.artifact == '' id: cache uses: actions/cache/restore@v6 with: - path: ${{ github.workspace }}/.newt-bin - key: newt-${{ runner.os }}-${{ runner.arch }}-${{ steps.newt.outputs.sha }} + path: ${{ steps.platform.outputs.dist }} + key: newt-${{ runner.os }}-${{ steps.newt.outputs.sha }}-${{ steps.newt.outputs.platforms }} - name: Report newt cache status + if: inputs.artifact == '' shell: bash env: CACHE_HIT: ${{ steps.cache.outputs.cache-hit }} @@ -58,35 +118,63 @@ runs: fi - name: Set up Go - if: steps.cache.outputs.cache-hit != 'true' + if: inputs.artifact == '' && steps.cache.outputs.cache-hit != 'true' uses: actions/setup-go@v7 with: go-version: 'stable' cache: false - name: Build newt - if: steps.cache.outputs.cache-hit != 'true' + if: inputs.artifact == '' && steps.cache.outputs.cache-hit != 'true' shell: bash env: - GOBIN: ${{ github.workspace }}/.newt-bin + CGO_ENABLED: 0 + GOPATH: ${{ runner.temp }}/newt-gopath + NEWT_SHA: ${{ steps.newt.outputs.sha }} + PLATFORMS: ${{ steps.platform.outputs.all }} + DIST: ${{ steps.platform.outputs.dist }} run: | go version - go install mynewt.apache.org/newt/newt@${{ steps.newt.outputs.sha }} + for platform in $PLATFORMS; do + goos=${platform%/*} + goarch=${platform#*/} + echo "Building newt for $platform" + GOOS=$goos GOARCH=$goarch \ + go install "mynewt.apache.org/newt/newt@$NEWT_SHA" + # Cross compiled binaries are installed to GOOS_GOARCH subdirectory + src="$GOPATH/bin/${goos}_${goarch}" + [ -d "$src" ] || src="$GOPATH/bin" + mkdir -p "$DIST/${goos}_${goarch}" + cp "$src"/newt* "$DIST/${goos}_${goarch}/" + done + ls -lR "$DIST" # Only master saves cache, so that it is shared with all pull # requests instead of being duplicated in each pull request scope - name: Save newt to cache if: >- - steps.cache.outputs.cache-hit != 'true' && + inputs.artifact == '' && steps.cache.outputs.cache-hit != 'true' && github.ref == 'refs/heads/master' && github.event_name != 'pull_request' uses: actions/cache/save@v6 with: - path: ${{ github.workspace }}/.newt-bin + path: ${{ steps.platform.outputs.dist }} key: ${{ steps.cache.outputs.cache-primary-key }} - name: Add newt to PATH shell: bash + env: + HOST: ${{ steps.platform.outputs.host }} + DIST: ${{ steps.platform.outputs.dist }} run: | - echo "${{ github.workspace }}/.newt-bin" >> "$GITHUB_PATH" - "${{ github.workspace }}/.newt-bin/newt" version + src="$DIST/$(echo "$HOST" | tr / _)" + if ! ls "$src"/newt* > /dev/null 2>&1; then + echo "::error::newt for $HOST not found" + exit 1 + fi + mkdir -p .newt-bin + cp "$src"/newt* .newt-bin/ + # Artifacts don't preserve file permissions + chmod +x .newt-bin/newt* + echo "$GITHUB_WORKSPACE/.newt-bin" >> "$GITHUB_PATH" + .newt-bin/newt version diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2c01cb171..94d72e555 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,15 +33,39 @@ permissions: contents: read jobs: + # Builds newt once per run for all platforms used by jobs of this + # workflow, other jobs take newt from artifact uploaded by this job. + newt: + name: Build newt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Build newt + id: newt + uses: ./.github/actions/newt-install + with: + platforms: windows/amd64 darwin/arm64 + - name: Upload newt + uses: actions/upload-artifact@v7 + with: + name: newt + path: ${{ steps.newt.outputs.dist }} + include-hidden-files: true + if-no-files-found: error + retention-days: 1 + # Downloads external repositories once per run, all Linux jobs use # project prepared by this job. prepare: name: Prepare project + needs: newt runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - name: Install newt uses: ./.github/actions/newt-install + with: + artifact: newt - name: Set up project uses: ./.github/actions/newt-project with: @@ -102,6 +126,7 @@ jobs: blinky-other-os: name: Build blinky + needs: newt strategy: fail-fast: false matrix: @@ -119,6 +144,8 @@ jobs: echo "$(brew --prefix)/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH - name: Install newt uses: ./.github/actions/newt-install + with: + artifact: newt - name: Set up project uses: ./.github/actions/newt-project with: @@ -252,6 +279,7 @@ jobs: targets-other-os: name: Build all test targets + needs: newt strategy: fail-fast: false matrix: @@ -269,6 +297,8 @@ jobs: echo "$(brew --prefix)/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH - name: Install newt uses: ./.github/actions/newt-install + with: + artifact: newt - name: Set up project uses: ./.github/actions/newt-project with: diff --git a/.github/workflows/cache_cleanup.yml b/.github/workflows/cache_cleanup.yml index 5e076eeb3..99f2d437c 100644 --- a/.github/workflows/cache_cleanup.yml +++ b/.github/workflows/cache_cleanup.yml @@ -50,11 +50,12 @@ jobs: // Caches created by master branch builds are saved with // unique keys (e.g. ccache-<job>-<run_id>-<attempt>), only // newest entry of each kind is used by later runs. Remove - // older entries to keep total cache size below limit. + // older entries to keep total cache size below limit. Kind + // is identified by all capture groups of matching pattern. const families = [ { re: /^(ccache-.+)-\d+-\d+$/ }, { re: /^(newt-repos-[^-]+)-[0-9a-f]+$/ }, - { re: /^(newt-[^-]+-[^-]+)-[0-9a-f]{40}$/ }, + { re: /^(newt-[^-]+)-[0-9a-f]{40}-(.+)$/ }, ]; const caches = await github.paginate( @@ -71,7 +72,7 @@ jobs: if (!family) { continue; } - const name = family[1]; + const name = family.slice(1).join('-'); const current = newest.get(name); if (!current) { newest.set(name, cache);
