Migrating to a bazel based CI system: 6 learnings
- 4. Hi,
I'm Or.
CI
Build with Ant and Makefiles
Maven CI Pipelines
Backend Engineering
…
Backend Engineering for2017
2011
2014
2019
- 7. ~5M LOC
> 1000 repos
2000+ Maven modules
2017
Teamcity
Maven
feedback
deployables
- 8. ~5M LOC
> 1000 repos
2000+ Maven modules
2017
Teamcity
Maven
feedback
deployables
building / broken
blockedblocked
blocked
blocked
- 16. .
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server]
└── FooServer.java
Migration 101 Bazel>>Maven >>
- 17. .
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server]
└── FooServer.java
Migration 101 Maven Bazel>> >>
Choose
Granularity
- 18. .
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server]
└── FooServer.java
Migration 101 Maven Bazel>> >>
Choose
Granularity
- 19. .
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server]
└── FooServer.java
Migration 101 Maven Bazel>> >>
Choose
Granularity
- 20. .
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server]
└── FooServer.java
Migration 101 Maven Bazel>> >>
Choose
Granularity
1:1:1 idiom - one target per
one directory, representing a
single package
- 21. .
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server]
└── FooServer.java
Migration 101 Maven Bazel>> >>
Choose
Granularity
>>
Convert to
Bazel rules
java_library
java_library
java_test
java_image
- 22. .
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server]
└── FooServer.java
java_library
java_library
java_test
java_binary
Migration 101 Maven Bazel>> >>
Choose
Granularity
>>
Convert to
Bazel rules
>>
internal
deps
java_library
java_library
java_test
java_image
- 23. .
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server]
└── FooServer.java
java_library
java_library
java_test
java_binary
@junit
@jetty
@guava20
Migration 101 Maven Bazel>> >>
Choose
Granularity
>>
Convert to
Bazel rules
>>
external
deps
java_library
java_library
java_test
java_image
@guava28
- 24. .
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server]
└── FooServer.java
java_library
java_library
java_test
java_binary
@junit
@jetty
Migration 101 Maven Bazel>> >>
Choose
Granularity
>>
Convert to
Bazel rules
>>
external
deps
java_library
java_library
java_test
java_image
@guava28
- 25. . [WORKSPACE.bazel]
├── foo-core [pom.xml]
│ └── src
│ ├── main
│ │ └── java
│ │ ├── [com.wix.foo.api] [BUILD.bazel]
│ │ │ └── FooBar.java
│ │ └── [com.wix.foo.utils] [BUILD.bazel]
│ │ ├── TimeUtils.java
│ │ └── NameUtils.java
│ └── test
│ └── java
│ └── [com.wix.foo.utils] [BUILD.bazel]
│ ├── TimeUtilsTest.java
│ └── NameUtilsTest.java
└── foo-server [pom.xml]
└── src
└── main
└── java
└── [com.wix.foo.server] [BUILD.bazel]
└── FooServer.java
Migration 101 Maven Bazel>> >>
Choose
Granularity
>>
Convert to
Bazel rules
>>
Add
deps
>>
Write
Bazel files
- 27. Code graph >> Targets graph
Third party
definitions
>> >>
✓
wix/exodus
>>
- 29. ✖ Missing compile/runtime deps
✖ Third party alignment
✖ Trying to read from ./src/test/resources
✖ Tests that try to download during test runtime
✖ More...
TECHNICAL DEBT == MORE WORK
exodus/troubleshooting
- 41. 1 Use a migration tool
2 Measure the system
- 46. ✓ Bazel training
✓ IDE issues
✓ Develop solutions!
Think local development!
CIOkay Local dev
Wix Bazel Local dev team:
○Tooling alignment
○Dev Cache
○Wix IntelliJ Bazel Plugin
- 47. 1 Use a migration tool
2 Measure the system
3 Think local dev experience
- 51. ✓ Remote cache and remote execution
✓ PR prechecks (no push to master)
✓ Automatic discovery of deployables
✓ Cloud based build server - no build queues
New Bazel CI Pipeline
- 54. 1 Use a migration tool
2 Measure the system
3 Think local dev experience
4 Run parallel CI pipelines
- 57. ✓ Remote cache - saves ~90% of execution
✓ Remote execution - improves throughput
5-8 minutes -
fully cached build
- 58. ✓ Remote cache - saves ~90% of execution
✓ Remote execution - improves throughput
✓ Repository cache - Saves downloading http binaries
✓ Docker cache - Saves downloading docker images
- 59. ✓ Remote cache - saves ~90% of execution
✓ Remote execution - improves throughput
✓ Repository cache - Saves downloading http binaries
✓ Docker cache - Saves downloading docker images
✓ Bazel flags - builds without the bytes, multithread digest...
- 60. When we started
we compiled Bazel from sources
Bazel keeps evolving
Each release
brought a lot of value, but also
required us to adjust
Tap to important issues, influence the priorities
Become a Bazel activist!
- 61. 1 Use a migration tool
2 Measure the system
3 Think local dev experience
4 Run parallel CI pipelines
5 Optimize for speed
- 63. Bazel works well with mono repo
All code in one place
Single bazel execution
✓ Single CI job
- 66. Goal: Virtual mono repository
java_library(
name = "core",
srcs = [":sources"],
deps = [
"//src/main/java/com/wix/local",
"@framework//src/main/java/com/wix/external",
],
)
git_repository(
name = "framework",
url = "git@github.com:wix/framework.git",
commit = "<auto-updated>",
)
- 67. Virtual mono-repo:
Virtual Mono-Repo Service holds all
repos of wix with their latest HEAD
version
Bazel wrapper generates a local bzl file
with `git_repository` definition of all
repositories
Each WORKSPACE file loads the
definition from the generated bzl file.
framework(031d53ce983d26a861d053c760190de669aa458d)
users(1202d41c7dc0739deddde3176c7de34ed9b978b7)
events(ab6d1d07477e3742fbc9f9c1e81e0ec402650b1b)
external_repos.bzl
git_repository(
name = "framework",
Commit = "031d53ce983d2
)
...
WORKSPACE.bazel
1
2
3
- 71. Migration in "Isolation Mode"
✓ Faster move to Bazel CI
✓ Faster feedback
✓ Faster deployables
✖ Keep Maven builds green
✖ Reproducibility hit
✖ Stale SNAPSHOT locally
- 72. Isolation Mode
Social Mode
java_library(
name = "core",
srcs = [":sources"],
deps = [
"//src/main/java/com/wix/local",
"@com_google_guava",
"@com_wix_framework",
],
)
scala_library(
name = "core",
srcs = [":sources"],
deps = [
"//src/main/java/com/wix/local",
"@com_google_guava",
"@framework//src/java/com/wixpress/lib",
],
)
- 73. ✖ Complex
✖ Non-revertible
java_library(
name = "core",
srcs = [":sources"],
deps = [
"//src/main/java/com/wix/local",
"@com_google_guava",
"@com_wix_framework",
],
)
java_library(
name = "core",
srcs = [":sources"],
deps = [
"//src/main/java/com/wix/local",
"@com_google_guava",
"@framework//src/java/com/wixpress/lib",
],
)
- 74. java_library(
name = "core",
srcs = [":sources"],
deps = [
"//src/main/java/com/wix/local",
"@com_google_guava",
"@com_wix_framework",
],
)
external_binary(
name = "com_wix_framework",
artifact = "com.wix.framework:1.0-SNAPSHOT"
)
external_source(
name = "com_wix_framework",
exports = [
"@framework//src/java/com/wixpress/lib"
]
)
workspace_rule
- 77. 1 Use a migration tool
2 Measure the system
3 Think local dev experience
4 Run parallel CI pipelines
5 Optimize for speed
6 Migrate poly-repo
- 79. Safe haven
CLOSED
✓ No more SNAPSHOT consumption
✓ All deployable from bazel
✓ All developers use bazel only
- 80. 1 Use a migration tool
2 Measure the system
3 Think local dev experience
4 Run parallel CI pipelines
5 Optimize for speed
6 Migrate poly-repo