diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d7e5d8e..1aaef44 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,10 @@ on: description: Build and test the osate-cli reactor. type: boolean default: true + build-extension: + description: Build the VS Code extension. + type: boolean + default: true test-extension: description: Run the VS Code extension test suites. type: boolean @@ -195,12 +199,20 @@ jobs: fi echo "osate2 pin: \`${{ steps.pin.outputs.sha }}\`" >> "$GITHUB_STEP_SUMMARY" + # Build only what the caller asked for. A release of one component has no + # reason to build the other two. - name: Build and test run: | args=(--skip-osate) - if [ "${{ inputs.test-extension }}" != "true" ]; then + if [ "${{ inputs.build-extension }}" != "true" ]; then + args+=(--skip-extension) + elif [ "${{ inputs.test-extension }}" != "true" ]; then args+=(--skip-extension-tests) fi + if [ "${{ inputs.build-cli }}" != "true" ]; then + args+=(--skip-cli) + fi + printf 'build-test-release %s\n' "${args[*]}" ./scripts/build-test-release "${args[@]}" # scripts/build-test-release stops before the CLI reactor's own reporting, @@ -242,7 +254,7 @@ jobs: target/build-provenance.properties - name: Upload the VS Code extension - if: inputs.upload-artifacts + if: inputs.upload-artifacts && inputs.build-extension uses: actions/upload-artifact@v6 with: name: vscode-extension diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8de4805..7fe32fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,6 +44,7 @@ jobs: uses: ./.github/workflows/build.yml with: build-cli: true + build-extension: true test-extension: true upload-artifacts: true diff --git a/.github/workflows/release-osate-cli.yml b/.github/workflows/release-osate-cli.yml index 3a2eadb..a08b2d6 100644 --- a/.github/workflows/release-osate-cli.yml +++ b/.github/workflows/release-osate-cli.yml @@ -49,18 +49,12 @@ jobs: echo "version=$pom" >> "$GITHUB_OUTPUT" echo "osate-cli version $pom" >> "$GITHUB_STEP_SUMMARY" - build: - needs: verify-version - uses: ./.github/workflows/build.yml - with: - build-cli: true - # Already covered by CI on main; a tag build does not need to relaunch VS Code. - test-extension: false - upload-artifacts: false - + # No separate build job: the package job needs the built dist tree on disk to + # run the packaging scripts, so calling the reusable build workflow as well + # meant building the language server, extension and CLI twice per release. package: - name: Package and publish - needs: [verify-version, build] + name: Build, package and publish + needs: verify-version runs-on: ubuntu-latest timeout-minutes: 150 permissions: @@ -82,15 +76,25 @@ jobs: distribution: temurin java-version: "21" + - name: Read the osate2 pin + id: pin + run: | + sha=$(git ls-files --stage osate2 | awk '$1 == "160000" { print $2 }') + if [ -z "$sha" ]; then + echo "No osate2 gitlink found." >&2 + exit 1 + fi + echo "sha=$sha" >> "$GITHUB_OUTPUT" + - name: Cache Maven dependencies uses: actions/cache@v5 with: path: | ~/.m2/repository !~/.m2/repository/org/osate - key: maven-${{ runner.os }}-${{ needs.build.outputs.osate-sha }}-${{ hashFiles('**/pom.xml') }} + key: maven-${{ runner.os }}-${{ steps.pin.outputs.sha }}-${{ hashFiles('**/pom.xml') }} restore-keys: | - maven-${{ runner.os }}-${{ needs.build.outputs.osate-sha }}- + maven-${{ runner.os }}-${{ steps.pin.outputs.sha }}- maven-${{ runner.os }}- # Populated by the build job, so this is expected to hit. @@ -101,7 +105,7 @@ jobs: path: | osate2/releng/org.osate.build.repository/target/repository ~/.m2/repository/org/osate/osate2-platform - key: osate-${{ runner.os }}-${{ needs.build.outputs.osate-sha }}-v1 + key: osate-${{ runner.os }}-${{ steps.pin.outputs.sha }}-v1 - name: Build OSATE if: steps.osate.outputs.cache-hit != 'true' @@ -116,7 +120,7 @@ jobs: clean install - name: Build the tooling and CLI - run: ./scripts/build-test-release --skip-osate --skip-extension-tests + run: ./scripts/build-test-release --skip-osate --skip-extension # build-release-artifacts.sh defaults to "auto" and would degrade to a # warning, silently shipping 4 of 8 packages. --nfpm below makes it fatal, @@ -197,9 +201,14 @@ jobs: git config user.email "41898282+github-actions[bot]@users.noreply.github.com" # A tap that has never been written to has no commits, so HEAD is - # unborn and there is no branch to push. Adopt whatever branch the - # clone put us on, falling back to main. - branch=$(git symbolic-ref --quiet --short HEAD || echo main) + # unborn and there is no branch to push. Pin the name rather than + # inheriting the runner's init.defaultBranch, which would otherwise + # decide whether the tap gets `main` or `master`. + if git rev-parse --quiet --verify HEAD >/dev/null; then + branch=$(git symbolic-ref --short HEAD) + else + branch=main + fi git checkout -B "$branch" mkdir -p Formula diff --git a/.github/workflows/release-server.yml b/.github/workflows/release-server.yml index 6b506fe..5587894 100644 --- a/.github/workflows/release-server.yml +++ b/.github/workflows/release-server.yml @@ -60,7 +60,9 @@ jobs: needs: verify-version uses: ./.github/workflows/build.yml with: + # This release ships the p2 repository only, so neither consumer is needed. build-cli: false + build-extension: false test-extension: false upload-artifacts: true diff --git a/.github/workflows/release-vscode.yml b/.github/workflows/release-vscode.yml index df561a5..7cd92b9 100644 --- a/.github/workflows/release-vscode.yml +++ b/.github/workflows/release-vscode.yml @@ -45,8 +45,10 @@ jobs: needs: verify-version uses: ./.github/workflows/build.yml with: - # The extension needs the language server; the CLI is unrelated to this release. + # The extension needs the language server; the CLI is unrelated to this + # release and is now genuinely skipped rather than built and ignored. build-cli: false + build-extension: true test-extension: true upload-artifacts: true diff --git a/.github/workflows/verify-credentials.yml b/.github/workflows/verify-credentials.yml index 3edf07d..419d964 100644 --- a/.github/workflows/verify-credentials.yml +++ b/.github/workflows/verify-credentials.yml @@ -86,23 +86,36 @@ jobs: fi cd /tmp/tap - branch=$(git symbolic-ref --quiet --short HEAD || echo main) + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + if git rev-parse --quiet --verify HEAD >/dev/null; then + branch=$(git symbolic-ref --short HEAD) + else + # A brand-new tap has no commits, so there is nothing to push and a dry + # run would fail for the wrong reason. Manufacture a local commit purely + # to give the push something to offer; --dry-run never writes it, and + # this clone is thrown away regardless. + # + # Pin the branch too, rather than inheriting whatever the runner's + # init.defaultBranch happens to be: for an empty tap that choice decides + # which branch the first release creates. + branch=main + git commit --quiet --allow-empty -m "write-access probe" + echo "Tap is empty; probing branch '$branch' with a local throwaway commit." + fi - # --dry-run exercises authentication and the ref update without writing. - if git push --dry-run "https://x-access-token:${TAP_TOKEN}@github.com/${TAP_REPO}.git" \ - "HEAD:refs/heads/$branch" 2>/dev/null; then + # --dry-run still authenticates and asks the server whether the ref + # update would be accepted, so a read-only token fails here. Nothing is + # written to the tap. + if git push --dry-run \ + "https://x-access-token:${TAP_TOKEN}@github.com/${TAP_REPO}.git" \ + "HEAD:refs/heads/$branch"; then echo "✅ HOMEBREW_TAP_TOKEN can push to \`$TAP_REPO\` (branch \`$branch\`)." >> "$GITHUB_STEP_SUMMARY" - elif [ -z "$(git rev-parse --quiet --verify HEAD 2>/dev/null)" ]; then - # An empty tap has nothing to push yet, so a dry run cannot prove write - # access. Report what is known instead of claiming success. - { - echo "⚠️ \`$TAP_REPO\` is empty, so push access could not be exercised." - echo "The first release will create \`Formula/osate-cli.rb\` on branch \`$branch\`." - } >> "$GITHUB_STEP_SUMMARY" else { echo "❌ HOMEBREW_TAP_TOKEN cannot push to \`$TAP_REPO\`." echo "The token needs **contents: read and write** on that repository." + echo "A read-only token still clones successfully, so only a push reveals this." } >> "$GITHUB_STEP_SUMMARY" exit 1 fi diff --git a/scripts/build-test-release b/scripts/build-test-release index a6d8694..33c318b 100755 --- a/scripts/build-test-release +++ b/scripts/build-test-release @@ -33,7 +33,9 @@ extension_dir="${repo_root}/vscode-extension" provenance_dir="${repo_root}/target" skip_osate=false +skip_extension=false skip_extension_tests=false +skip_cli=false usage() { cat <<'EOF' @@ -49,9 +51,12 @@ Options: are verified before the remaining phases run. Intended for CI, where the OSATE output is restored from a cache keyed on the osate2 submodule commit. + --skip-extension Do not build the VS Code extension. Implies + --skip-extension-tests. --skip-extension-tests Skip the VS Code extension test suite. The integration tests download VS Code and need a display, which is not always available. + --skip-cli Do not build the osate-cli reactor. -h, --help Show this help. EOF } @@ -61,9 +66,16 @@ while [[ $# -gt 0 ]]; do --skip-osate) skip_osate=true ;; + --skip-extension) + skip_extension=true + skip_extension_tests=true + ;; --skip-extension-tests) skip_extension_tests=true ;; + --skip-cli) + skip_cli=true + ;; -h | --help) usage exit 0 @@ -159,13 +171,17 @@ mvn \ -Dtycho.localArtifacts=ignore \ clean verify -echo "Building VS Code extension" +if [[ "${skip_extension}" == true ]]; then + echo "Skipping VS Code extension" +else + echo "Building VS Code extension" -mvn \ - -T6 \ - -f "${repo_root}/vscode-extension/pom.xml" \ - -Dtycho.localArtifacts=ignore \ - clean verify + mvn \ + -T6 \ + -f "${repo_root}/vscode-extension/pom.xml" \ + -Dtycho.localArtifacts=ignore \ + clean verify +fi if [[ "${skip_extension_tests}" == true ]]; then echo "Skipping VS Code extension tests" @@ -192,12 +208,16 @@ else ) fi -echo "Building OSATE CLI" +if [[ "${skip_cli}" == true ]]; then + echo "Skipping OSATE CLI" +else + echo "Building OSATE CLI" -mvn \ - -T6 \ - -f "${repo_root}/osate-cli/pom.xml" \ - verify + mvn \ + -T6 \ + -f "${repo_root}/osate-cli/pom.xml" \ + verify +fi duplicate_bundles=$( find "${plugins_dir}" -type f -name '*.jar' |