Log In
Or create an account ->
Imperial Library
Home
About
News
Upload
Forum
Help
Login/SignUp
Index
Forewords
Preface
Why Did We Write This Book?
Why You Should Read This Book
What This Book Is Not
Conventions Used in This Book
Using Code Examples
O’Reilly Safari
How to Contact Us
Acknowledgments
1. Continuous Delivery: Why and What
Setting the Scene
Enabling Developers: The Why
Rapid Feedback Reduces Context Switching
Automatic, Repeatable, and Reliable Releases
Codifying the Definition of “Done”
Exploring a Typical Build Pipeline: The What
Core Build Pipeline Stages
Impact of Container Technology
Changes with Contemporary Architectures
Summary
2. Evolution of Java Development
Requirements of Modern Java Applications
Need for Business Speed and Stability
Rise of the API Economy
Opportunities and Costs of the Cloud
Modularity Redux: Embracing Small Services
Impact on Continuous Delivery
Evolution of Java Deployment Platforms
WARs and EARs: The Era of Application Server Dominance
Executable Fat JARs: Emergence of Twelve-Factor Apps
Container Images: Increasing Portability (and Complexity)
Function as a Service: The Emergence of “Serverless”
Impact of Platforms on Continuous Delivery
DevOps, SRE, and Release Engineering
Development and Operations
Site Reliability Engineering
Release Engineering
Shared Responsibility, Metrics, and Observability
Summary
3. Designing Architecture for Continuous Delivery
Fundamentals of Good Architecture
Loose Coupling
High Cohesion
Coupling, Cohesion, and Continuous Delivery
Architecture for Business Agility
Bad Architecture Limits Business Velocity
Complexity and Cost of Change
Best Practices for API-Driven Applications
Build APIs “Outside-In”
Good APIs Assist Continuous Testing and Delivery
Deployment Platforms and Architecture
Designing Cloud-Native “Twelve-Factor” Applications
Cultivating Mechanical Sympathy
Design and Continually Test for Failure
The Move Toward Small Services
Challenges for Delivering Monolithic Applications
Microservices: SOA Meets Domain-Driven Design
Functions, Lambdas, and Nanoservices
Architecture: “The Stuff That’s Hard to Change”
Summary
4. Deployment Platforms, Infrastructure, and Continuous Delivery of Java Apps
Functionality Provided by a Platform
Essential Development Processes
Traditional Infrastructure Platforms
Traditional Platform Components
Challenges with Traditional Infrastructure Platforms
Benefits of Being Traditional
CI/CD on Traditional Infrastructure Platforms
Cloud (IaaS) Platform
Looking Inside the Cloud
Cloud Challenges
Benefits of the Cloud
Continuously Delivering into the Cloud
Platform as a Service
Peeking Inside a PaaS
PaaS Challenges
Benefits of PaaS
CI/CD and PaaS
Containers (Docker)
Container Platform Components
Container Challenges
Container Benefits
Continuously Delivering Containers
Kubernetes
Core Concepts of Kubernetes
Kubernetes Challenges
Benefits of Kubernetes
Continuous Delivery on Kubernetes
Function-as-a-Service/Serverless Functions
FaaS Concepts
Challenges of FaaS
FaaS Benefits
CI/CD and FaaS
Working with Infrastructure as Code
Summary
5. Building Java Applications
Breaking Down the Build Process
Automating the Build
Build Dependencies
External Dependencies
Multimodule Projects
Multiple Repositories (or a Monorepo)?
Plugins
Releasing and Publishing Artifacts
Java Build Tooling Overview
Ant
Maven
Gradle
Bazel, Pants, and Buck
Other JVM Build Tools: SBT and Leiningen
Make
Choosing a Build Tool
Summary
6. Additional Build Tooling and Skills
Linux, Bash, and Basic CLI Commands
Users, Permissions, and Groups
Working with the Filesystem
Viewing and Editing Text
Joining Everything Together: Redirects, Pipes, and Filters
Searching and Manipulating Text: grep, awk, and sed
Diagnostic Tooling: top, ps, netstat, and iostat
HTTP Calls and JSON Manipulation
curl
HTTPie
jq
Basic Scripting
xargs
Pipes and Filters
Loops
Conditionals
Summary
7. Packaging Applications for Deployment
Building a JAR: Step-by-Step
Building a Fat Executable “Uber” JAR
Maven Shade Plugin
Building Spring Boot Uber JARs
Skinny JARs—Deciding Not to Build Fat JARs
Building WAR Files
Packaging for the Cloud
Cooking Configuration: Baking or Frying Machines
Building RPMs and DEBs OS Packages
Additional OS Package Build Tools (with Windows Support)
Creating Machine Images for Multiple Clouds with Packer
Additional Tools for Creating Machine Images
Building Containers
Creating Container Images with Docker
Fabricating Docker Images with fabric8
Packaging FaaS Java Applications
Summary
8. Working Locally (Like It Was Production)
Challenges with Local Development
Mocking, Stubbing, and Service Virtualization
Pattern #1: Profiles, Mocks, and Stubs
Mocking with Mockito
Pattern #2: Service Virtualization and API Simulation
Virtualizing Services with Hoverfly
VMs: Vagrant and Packer
Installing Vagrant
Creating a Vagrantfile
Pattern #3: Production-in-a-Box
Containers: Kubernetes, minikube, and Telepresence
Introducing the “Docker Java Shop” Sample App
Building Java Applications and Container Images
Deploying into Kubernetes
Simple Smoke Test
Building the Remaining Applications
Deploying the Entire Java Application in Kubernetes
Viewing the Deployed Application
Telepresence: Working Remotely, Locally
Pattern #4: Environment Leasing
FaaS: AWS Lamba and SAM Local
Installing SAM Local
AWS Lambda Scaffolding
Testing AWS Lambda Event Handling
Smoke Testing with SAM Local
FaaS: Azure Functions and VS Code
Installing Azure Function Core Tools
Building and Testing Locally
Testing Remotely, Locally Using VS Code
Summary
9. Continuous Integration: The First Steps in Creating a Build Pipeline
Why Continuous Integration?
Implementing CI
Centralized Versus Distributed Version-Control Systems
Git Primer
Core Git CLI Commands
Hub: An Essential Tool for Git and GitHub
Working Effectively with DVCS
Trunk-based Development
Feature Branching
Gitflow
No One-Size Fits All: How to Choose a Branching Strategy
Code Reviews
What to Look For
Automation: PMD, Checkstyle, and FindBugs
Reviewing Pull Requests
Automating Builds
Jenkins
Getting Your Team Onboard
Merge Code Regularly
“Stop the Line!”: Managing Broken Builds
Don’t @Ignore Tests
Keep the Build Fast
CI of the Platform (Infrastructure as Code)
Summary
10. Deploying and Releasing from the Pipeline
Introducing the Extended Java Shop Application
Separating Deployment and Release
Deploying Applications
Creating a Container Image
Deployment Mechanisms
It All Starts (and Ends) with Health Checks
Deployment Strategies
Working with Unmanaged Clusters
Changing Databases
Releasing Functionality
Feature Flags
Semantic Versioning (semver)
Backward Compatibility and Versions in APIs
Multiple-Phase Upgrades
Managing Configuration and Secrets
“Baked-In” Configuration
Externalized Configuration
Handling Secrets
Summary
11. Functional Testing: Correctness and Acceptance
Why Test Software?
What to Test? Introducing Agile Testing Quadrants
Continuous Testing
Building the Right Feedback Loop
Turtles All the Way Down
Synthetic Transactions
End-to-End Testing
Acceptance Testing
Behavior-Driven Development
Stubbing or Virtualizing Third-Party Services
Bringing It All Together
Consumer-Driven Contracts
RESTful API Contracts
Message Contracts
Component Testing
Embedded Data Stores
In-Memory Message Queues
Test Doubles
Creating Internal Resources/Interfaces
In-Process Versus Out-Of-Process
Integration Testing
Verifying External Interactions
Testing Fault Tolerance
Unit Testing
Sociable Unit Testing
Solitary Unit Testing
Dealing with Flaky Tests
Data
Resource That Is Not Available Yet
Nondeterministic Events
If Nothing Else Works
Testing Outside-In Versus Testing Inside-Out
Outside-In
Inside-Out
Putting It All Together Within the Pipeline
How Much Testing Is Enough?
Summary
12. System-Quality Attributes Testing: Validating Nonfunctional Requirements
Why Test Nonfunctional Requirements?
Code Quality
Architectural Quality
ArchUnit: Unit-Testing Architecture
Generate Design-Quality Metrics with JDepend
Performance and Load Testing
Basic Performance Testing with Apache Benchmark
Load Testing with Gatling
Security, Vulnerabilities, and Threats
Code-Level Security Verification
Dependency Verification
Deployment Platform-Specific Security Issues
Next Steps: Threat Modeling
Chaos Testing
Causing Chaos in Production (Bring in the Monkeys)
Causing Chaos in Preproduction
How Much NFR Testing Is Enough?
Summary
13. Observability: Monitoring, Logging, and Tracing
Observability and Continuous Delivery
Why Observe?
What to Observe: Application, Network, and Machine
How to Observe: Monitoring, Logging, and Tracing
Alerting
Designing Systems for Observability
Metrics
Type of Metrics
Dropwizard Metrics
Spring Boot Actuator
Micrometer
Best Practices with Metrics
Logging
Forms of Logging
SLF4J
Log4j 2
Logging Best Practices
Request Tracing
Traces, Spans, and Baggage
Java Tracing: OpenZipkin, Spring Sleuth, and OpenCensus
Recommended Practices for Tracing
Exception Tracking
Airbrake
System-Monitoring Tooling
collectd
rsyslog
Sensu
Collection and Storage
Prometheus
Elastic-Logstash-Kibana
Visualization
Visualization for Business
Operational Visualization
Visualization for Developers
Summary
14. Migrating to Continuous Delivery
Continuous Delivery Capabilities
Picking Your Migration Project
Situational Awareness
The Cynefin Framework and Continuous Delivery
All Models Are Wrong, Some Are Useful
Bootstrapping Continuous Delivery
Measuring Continuous Delivery
Start Small, Experiment, Learn, Share, and Repeat
Increase Adoption: Leading Change
Additional Guidance and Tips
Bad Practices and Common Antipatterns
Ugly Architecture: To Fix, or Not to Fix
Summary
15. Continuous Delivery and Continuous Improvement
Start from Where You Are
Build on Solid Technical Foundations
Continuously Deliver Value (Your Highest Priority)
Increase Shared Responsibility of Software
Promote Fast Feedback and Experimentation
Expand Continuous Delivery in an Organization
Continuous Improvement
Summary
Index
← Prev
Back
Next →
← Prev
Back
Next →