Skip to content

Commit eb81376

Browse files
authored
Refactor Buildpack (#165)
1 parent a09ef79 commit eb81376

File tree

226 files changed

+4280
-14089
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

226 files changed

+4280
-14089
lines changed

.github/workflows/ci.yml

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,38 @@ permissions:
1010
contents: read
1111

1212
jobs:
13+
lint:
14+
runs-on: ubuntu-24.04
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v5
18+
- name: Install Ruby and dependencies
19+
uses: ruby/setup-ruby@v1
20+
with:
21+
bundler-cache: true
22+
ruby-version: "3.4"
23+
- name: Install shfmt
24+
run: sudo apt-get install shfmt
25+
- run: make lint-scripts
26+
- run: make check-format
27+
- run: make lint-ruby
28+
1329
hatchet:
1430
name: "Hatchet (${{ matrix.stack }})"
15-
runs-on: ubuntu-22.04
31+
runs-on: ubuntu-24.04
32+
needs: lint
1633
strategy:
1734
fail-fast: false
1835
matrix:
19-
stack: [ "heroku-22", "heroku-24"]
36+
stack: ["heroku-22", "heroku-24"]
2037
env:
2138
HATCHET_APP_LIMIT: 100
22-
HATCHET_RUN_MULTI: 1
23-
HATCHET_EXPENSIVE_MODE: 1
24-
PARALLEL_SPLIT_TEST_PROCESSES: 6
39+
PARALLEL_SPLIT_TEST_PROCESSES: 20
2540
HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
2641
HEROKU_API_USER: ${{ secrets.HEROKU_API_USER }}
2742
HEROKU_DISABLE_AUTOUPDATE: 1
28-
# TODO: Remove once Hatchet supports GitHub Actions natively:
29-
# https://github.com/heroku/hatchet/pull/189
30-
HATCHET_BUILDPACK_BRANCH: ${{ github.head_ref || github.ref_name }}
3143
HATCHET_BUILDPACK_BASE: https://github.com/heroku/heroku-buildpack-gradle
32-
# Default stack for all Heroku apps created by Hatchet
33-
DEFAULT_APP_STACK: ${{ matrix.stack }}
44+
HATCHET_DEFAULT_STACK: ${{ matrix.stack }}
3445
steps:
3546
- uses: actions/checkout@v5
3647
- name: Install Ruby and dependencies
@@ -43,41 +54,14 @@ jobs:
4354
- name: Run Hatchet integration tests
4455
run: bundle exec parallel_split_test test/spec/
4556

46-
buildpack-testrunner:
47-
runs-on: ubuntu-22.04
48-
env:
49-
SHUNIT_HOME: /tmp/shunit2-2.1.6
50-
# Note the missing STACK environment variable here. This works since there is a default value in the buildpack
51-
# source. I ported this as-is from the Travis config. Given we're trying to get rid of testrunner entirely,
52-
# it will stay like this. If we, for some reason, decide to keep testrunner, we should look into a fixed STACK env var.
57+
container-test:
58+
runs-on: ubuntu-24.04
5359
steps:
54-
- uses: actions/checkout@v5
55-
- uses: actions/setup-java@v5
56-
with:
57-
distribution: zulu
58-
java-version: 8
59-
- name: Download and unpack shunit 2.1.6
60-
run: curl -sSf --retry 3 --retry-connrefused --connect-timeout 5 https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/shunit2/shunit2-2.1.6.tgz | tar xz -C /tmp/
61-
- name: Clone heroku-buildpack-testrunner
62-
run: git clone https://github.com/heroku/heroku-buildpack-testrunner.git /tmp/testrunner
63-
- name: Apply heroku-buildpack-testrunner patches to enforce bash shell
64-
run: |
65-
cd /tmp/testrunner
66-
git apply <<'EOF'
67-
diff --git a/bin/run b/bin/run
68-
index 0d5b790..a0ff25c 100755
69-
--- a/bin/run
70-
+++ b/bin/run
71-
@@ -101,7 +101,7 @@ for bp in ${@}; do
72-
suite_start_time="$(date +%s)"
73-
74-
echo " TEST SUITE: $(basename ${f})"
75-
- ${SHUNIT_HOME?"'SHUNIT_HOME' environment variable must be set"}/src/shunit2 ${f} | indent
76-
+ /bin/bash ${SHUNIT_HOME?"'SHUNIT_HOME' environment variable must be set"}/src/shunit2 ${f} | indent
77-
exit_code=$(max ${exit_code} ${PIPESTATUS[0]})
78-
79-
suite_end_time="$(date +%s)"
80-
81-
EOF
82-
- name: Execute buildpack-testrunner
83-
run: /tmp/testrunner/bin/run .
60+
- name: Checkout
61+
uses: actions/checkout@v5
62+
# These test both the local development `make run` workflow and that `bin/report` completes successfully
63+
# for both passing and failing builds (since `bin/report` can't easily be tested via Hatchet tests).
64+
- name: Run buildpack using default app fixture
65+
run: make run
66+
#- name: Run buildpack using an app fixture that's expected to fail
67+
# run: make run FIXTURE=spec/fixtures/failing/

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
1+
.idea/
2+
*.swp
3+
target
4+
*.iml
15
.DS_Store
2-
.idea
6+
.rspec_status
7+
test/spec/fixtures/repos/github

.rubocop.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
plugins:
2+
- rubocop-rspec
3+
4+
AllCops:
5+
NewCops: enable
6+
7+
Layout/TrailingWhitespace:
8+
# Required since we use heredocs to assert against Hatchet output, and sometimes that output
9+
# contains trailing newlines which we must match against. The alternative is to end the lines
10+
# with the unsightly `#{' '}` workaround.
11+
AllowInHeredoc: true
12+
13+
Metrics/BlockLength:
14+
Enabled: false
15+
16+
RSpec/DescribeClass:
17+
Enabled: false
18+
19+
RSpec/ExampleLength:
20+
Enabled: false
21+
22+
RSpec/Focus:
23+
# Disable auto-correct otherwise format-on-save will remove the annotation
24+
# whilst developing locally.
25+
AutoCorrect: false
26+
27+
RSpec/MultipleExpectations:
28+
Enabled: false
29+
30+
Style/TrailingCommaInArrayLiteral:
31+
EnforcedStyleForMultiline: consistent_comma
32+
33+
Style/TrailingCommaInHashLiteral:
34+
EnforcedStyleForMultiline: consistent_comma

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
11
# Changelog
22

3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6+
37
## [Unreleased]
48

9+
### Added
10+
11+
- Gradle daemon lifecycle management for faster builds. ([#165](https://github.com/heroku/heroku-buildpack-gradle/pull/165))
12+
13+
### Changed
14+
15+
- Framework detection now uses Gradle dependency resolution instead of build file parsing for more reliable detection across all DSL syntax, version catalogs, and dependency sources. ([#165](https://github.com/heroku/heroku-buildpack-gradle/pull/165))
16+
- Improved error messages with detailed troubleshooting steps, documentation links, and local reproduction guidance. ([#165](https://github.com/heroku/heroku-buildpack-gradle/pull/165))
17+
18+
### Removed
19+
20+
- `GRADLE_TESTPACK_LEGACY_TASK` legacy feature - always exclude `check` task during builds instead of just `test` task. ([#165](https://github.com/heroku/heroku-buildpack-gradle/pull/165))
21+
- Gradle wrapper installation feature. Projects must include their own Gradle wrapper (`gradlew`). To add a wrapper, run `gradle wrapper` locally and commit the generated files. The buildpack's default wrapper provision was deprecated in 2014 (see [#17](https://github.com/heroku/heroku-buildpack-gradle/pull/17)). ([#165](https://github.com/heroku/heroku-buildpack-gradle/pull/165))
522

623
## [v43] - 2025-07-14
724

Gemfile

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1-
source "https://rubygems.org"
1+
# frozen_string_literal: true
22

3-
gem 'heroku_hatchet'
4-
gem 'rspec-retry'
5-
gem 'rspec-expectations'
6-
gem 'parallel_split_test'
7-
gem 'java-properties'
3+
source 'https://rubygems.org'
4+
5+
ruby '>= 3.2', '< 3.5'
6+
7+
group :test, :development do
8+
gem 'heroku_hatchet'
9+
gem 'parallel_split_test'
10+
gem 'rspec-core'
11+
gem 'rspec-expectations'
12+
gem 'rspec-retry'
13+
gem 'rubocop', require: false
14+
gem 'rubocop-rspec', require: false
15+
end

Gemfile.lock

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
GEM
22
remote: https://rubygems.org/
33
specs:
4+
ast (2.4.3)
45
base64 (0.3.0)
56
diff-lcs (1.6.2)
67
erubis (2.7.0)
7-
excon (1.2.8)
8+
excon (1.3.0)
89
logger
910
heroics (0.1.3)
1011
base64
@@ -19,41 +20,77 @@ GEM
1920
rrrretry (~> 1)
2021
thor (~> 1)
2122
threaded (~> 0)
22-
java-properties (0.3.0)
23+
json (2.13.2)
24+
language_server-protocol (3.17.0.5)
25+
lint_roller (1.1.0)
2326
logger (1.7.0)
2427
moneta (1.0.0)
2528
multi_json (1.17.0)
26-
parallel (1.20.1)
29+
parallel (1.27.0)
2730
parallel_split_test (0.10.0)
2831
parallel (>= 0.5.13)
2932
rspec-core (>= 3.9.0)
33+
parser (3.3.9.0)
34+
ast (~> 2.4.1)
35+
racc
3036
platform-api (3.8.0)
3137
heroics (~> 0.1.1)
3238
moneta (~> 1.0.0)
3339
rate_throttle_client (~> 0.1.0)
40+
prism (1.4.0)
41+
racc (1.8.1)
42+
rainbow (3.1.1)
3443
rate_throttle_client (0.1.2)
44+
regexp_parser (2.11.2)
3545
rrrretry (1.0.0)
36-
rspec-core (3.13.0)
46+
rspec-core (3.13.5)
3747
rspec-support (~> 3.13.0)
3848
rspec-expectations (3.13.5)
3949
diff-lcs (>= 1.2.0, < 2.0)
4050
rspec-support (~> 3.13.0)
4151
rspec-retry (0.6.2)
4252
rspec-core (> 3.3)
43-
rspec-support (3.13.4)
53+
rspec-support (3.13.5)
54+
rubocop (1.80.2)
55+
json (~> 2.3)
56+
language_server-protocol (~> 3.17.0.2)
57+
lint_roller (~> 1.1.0)
58+
parallel (~> 1.10)
59+
parser (>= 3.3.0.2)
60+
rainbow (>= 2.2.2, < 4.0)
61+
regexp_parser (>= 2.9.3, < 3.0)
62+
rubocop-ast (>= 1.46.0, < 2.0)
63+
ruby-progressbar (~> 1.7)
64+
unicode-display_width (>= 2.4.0, < 4.0)
65+
rubocop-ast (1.46.0)
66+
parser (>= 3.3.7.2)
67+
prism (~> 1.4)
68+
rubocop-rspec (3.7.0)
69+
lint_roller (~> 1.1)
70+
rubocop (~> 1.72, >= 1.72.1)
71+
ruby-progressbar (1.13.0)
4472
thor (1.4.0)
4573
threaded (0.0.4)
74+
unicode-display_width (3.1.5)
75+
unicode-emoji (~> 4.0, >= 4.0.4)
76+
unicode-emoji (4.0.4)
4677
webrick (1.9.1)
4778

4879
PLATFORMS
80+
arm64-darwin-24
4981
ruby
5082

5183
DEPENDENCIES
5284
heroku_hatchet
53-
java-properties
5485
parallel_split_test
86+
rspec-core
5587
rspec-expectations
5688
rspec-retry
89+
rubocop
90+
rubocop-rspec
91+
92+
RUBY VERSION
93+
ruby 3.4.5p51
5794

5895
BUNDLED WITH
59-
2.6.9
96+
2.7.1

Makefile

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# These targets are not files
2+
.PHONY: lint lint-scripts check-format format run publish
3+
4+
STACK ?= heroku-24
5+
FIXTURE ?= test/spec/fixtures/repos/simple-http-service-gradle-8-groovy
6+
7+
# Converts a stack name of `heroku-NN` to its build Docker image tag of `heroku/heroku:NN-build`.
8+
STACK_IMAGE_TAG := heroku/$(subst -,:,$(STACK))-build
9+
10+
lint: lint-scripts check-format lint-ruby
11+
12+
lint-scripts:
13+
@git ls-files -z --cached --others --exclude-standard 'bin/*' 'etc/*' 'lib/*' 'opt/*' | xargs -0 shellcheck --check-sourced --color=always
14+
15+
lint-ruby:
16+
@bundle exec rubocop
17+
18+
check-format:
19+
@shfmt -f . | grep -v "vendor/" | grep -v "test/spec/fixtures/" | xargs shfmt --diff
20+
21+
format:
22+
@shfmt -f . | grep -v "vendor/" | grep -v "test/spec/fixtures/" | xargs shfmt --write --list
23+
24+
run:
25+
@echo "Running buildpack using: STACK=$(STACK) FIXTURE=$(FIXTURE)"
26+
@docker run --rm -v $(PWD):/src:ro --tmpfs /app --platform linux/amd64 -e "HOME=/app" -e "STACK=$(STACK)" "$(STACK_IMAGE_TAG)" \
27+
bash -euo pipefail -c '\
28+
mkdir /tmp/buildpack /tmp/build /tmp/cache /tmp/env; \
29+
cp -r /src/{bin,lib} /tmp/buildpack; \
30+
cp -rT /src/$(FIXTURE) /tmp/build; \
31+
cd /tmp/buildpack; \
32+
unset $$(printenv | cut -d '=' -f 1 | grep -vE "^(HOME|LANG|PATH|STACK)$$"); \
33+
echo -e "\n~ Detect:" && ./bin/detect /tmp/build; \
34+
echo -e "\n~ Compile:" && { ./bin/compile /tmp/build /tmp/cache /tmp/env || COMPILE_FAILED=1; }; \
35+
echo -e "\n~ Report:" && ./bin/report /tmp/build /tmp/cache /tmp/env; \
36+
[[ "$${COMPILE_FAILED:-}" == "1" ]] && exit 0; \
37+
[[ -f /tmp/build/bin/compile ]] && { echo -e "\n~ Compile (Inline Buildpack):" && (source ./export && /tmp/build/bin/compile /tmp/build /tmp/cache /tmp/env); }; \
38+
echo -e "\n~ Release:" && ./bin/release /tmp/build; \
39+
echo -e "\nBuild successful!"; \
40+
'
41+
@echo
42+
43+
publish:
44+
@etc/publish.sh

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ It uses Gradle to build your application and OpenJDK to run it.
1010
1. Install the [Gradle Wrapper](http://www.gradle.org/docs/current/userguide/gradle_wrapper.html) into your project.
1111
- This allows control over the Gradle version and exact distribution to be used.
1212
2. Specify the Java version to be used as per [these instructions](https://devcenter.heroku.com/articles/java-support#specifying-a-java-version).
13-
3. If you are not using Spring Boot or Ratpack, then follow the instructions for [configuring your build](https://devcenter.heroku.com/articles/deploying-gradle-apps-on-heroku).
13+
3. If you are not using Spring Boot, then follow the instructions for [configuring your build](https://devcenter.heroku.com/articles/deploying-gradle-apps-on-heroku).
1414

1515
You do not need to explicitly declare that your project should use this buildpack.
1616
The presence of a `gradlew` script in the root of your project will allow the fact that your app is built with Gradle to detected.

0 commit comments

Comments
 (0)