continuous_integration_ci

Table of Contents

Continuous Integration (CI)

DevOps is the union of people, process, and products to enable CONTINUOUS DELIVERY of value to our end users.” – Donovan Brown of Microsoft

Return to Continuous Integration (CI) / Continuous Delivery (CD) = CI/CD, Continuous, DevOps Toolchain, DevOps, Computer science topics, Agile or Software engineering

Continuous integration


Summarize this topic in 25 paragraphs. Put a section heading for each paragraph. You MUST put double square brackets around each computer buzzword or jargon or technical words. Answer in MediaWiki syntax.

Continuous Integration (CI) is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily — leading to multiple integrations per day. Each integration is automatically verified by building the project and running automated tests against the build. This approach aims to reduce integration problems, allow for faster development cycles, and increase project quality.

Introduction to Continuous Integration

Continuous Integration (CI) is a development practice where developers frequently integrate code into a shared repository, preferably multiple times a day. Each integration is then verified by an automated build and automated tests. The key goals of CI are to find and address bugs quicker, improve software quality, and reduce the time it takes to validate and release new software updates.

The Importance of CI

CI plays a crucial role in the software development lifecycle, facilitating rapid feedback on the codebase's health. It allows teams to detect errors early in the development process, making them easier and less costly to fix. By automating the build and testing processes, CI also helps in maintaining a high quality of the code, enhancing the overall productivity of the development team.

Key Components of CI

The core components of a CI system include a source code repository, a build system, and an automated testing framework. The source code repository is where the code is stored and shared among the development team. The build system compiles the code into executable applications, and the automated testing framework runs tests on the builds to ensure they meet the desired quality standards.

CI Workflow

The typical workflow of a CI process starts with developers committing changes to the source code repository. The CI server detects these changes and triggers the build process. If the build is successful, the CI server then triggers the automated tests. If the tests pass, the build is considered stable and can be deployed to a testing or production environment.

Benefits of Continuous Integration

Implementing CI brings several benefits to the software development process. It encourages a culture of continuous improvement, enhances visibility into the development process, and enables early detection of integration issues. Additionally, CI supports a faster development pace, improves developer productivity, and leads to higher quality software.

Challenges in Implementing CI

While CI offers numerous advantages, there are also challenges in its implementation. These include the need for a solid automation framework, the initial setup and maintenance of the CI infrastructure, and ensuring consistent commit practices among developers. Overcoming these challenges is crucial for a successful CI implementation.

CI Tools and Technologies

There are many tools available that facilitate the implementation of CI, including Jenkins, Travis CI, CircleCI, and GitLab CI. These tools automate the process of building and testing code, making it easier for development teams to adopt CI practices.

Integrating CI with Version Control

A critical aspect of CI is its integration with version control systems (VCS), such as Git, Subversion, or Mercurial. This integration ensures that any commit to the repository automatically triggers the CI pipeline, starting the build and test processes without manual intervention.

Automated Testing in CI

Automated testing is a cornerstone of CI. It includes unit tests, integration tests, and functional tests, which are run automatically on every build. This ensures that the application remains stable and that new changes do not break existing functionality.

The Role of Build Automation

Build automation is another critical component of CI. It involves compiling the code into executable builds using tools like Maven, Gradle, or Ant. This process is fully automated and ensures that the application can be built consistently in any environment.

Continuous Deployment and Delivery

Continuous Deployment (CD) and Continuous Delivery are practices often associated with CI. While CI focuses on the integration and testing phases, CD takes it a step further by automatically deploying all changes to a production environment after the build and tests are successful.

Best Practices for CI

Adopting best practices is crucial for maximizing the benefits of CI. These include maintaining a single source code repository, automating the build process, keeping the build fast, testing in a clone of the production environment, and making it easy for anyone to get the latest executable version.

Monitoring and Feedback in CI

Monitoring the CI process and providing rapid feedback to developers is essential. Tools integrated into the CI pipeline can notify developers of build failures, test failures, or deployment issues, allowing for immediate action to rectify problems.

Security Considerations in CI

Security is a critical aspect of CI. Implementing security checks, such as static code analysis and vulnerability scanning, within the CI pipeline can help identify security issues early in the development cycle.

CI in Agile Development

CI complements Agile development methodologies by supporting iterative and incremental development. It allows teams to integrate and validate changes more frequently, aligning with Agile's emphasis on rapid and flexible response to change.

CI for Large Teams

For large development teams, CI is particularly beneficial as it helps manage the complexity of integrating code from multiple developers working on different parts of a project. It ensures that the codebase remains stable and that changes are compatible with each other.

CI in DevOps

In the context of DevOps, CI is a foundational practice that bridges the gap between development and operations teams. It ensures that code changes are automatically built, tested, and prepared for release to production, facilitating a smoother and faster delivery process.

The future of CI includes advancements in automation, more sophisticated testing frameworks, integration with artificial intelligence for predictive analytics, and enhanced security practices. These trends aim to make CI even more efficient and effective in supporting software development.

Conclusion

Continuous Integration is a critical practice in modern software development, enabling teams to integrate changes frequently, detect errors early, and maintain high-quality software. By automating builds and tests, and closely integrating with version control systems, CI facilitates a more efficient and error-free development process. Adopting CI, along with its best practices, can significantly improve the software development lifecycle, making it faster, more reliable, and more productive.


Continuous Integration via GitHub Actions

In 20 paragraphs give code examples in Python, Flask, Django, JavaScript, React, Vue.js, TypeScript, Angular, Java, Spring Boot, Kotlin, C# .NET, F#, PowerShell, T-SQL, PL/SQL, C++, C, Go, Rust, Scala, Clojure, Haskell, PHP, Swift, Ruby, R, COBOL, Fortran if possible. Put a section heading for each paragraph. You MUST put double square brackets around each computer buzzword or jargon or technical words. Answer in MediaWiki syntax.

Given the vast range of languages and frameworks you've asked about, along with the specificity of using GitHub Actions as the CI/CD platform, let's focus on demonstrating how GitHub Actions can be configured to automate testing and deployment tasks across a variety of environments. This selection provides insight into the flexibility and broad applicability of GitHub Actions for Continuous Integration (CI) and Continuous Deployment (CD) practices.

GitHub Actions Introduction

GitHub Actions is a CI/CD platform that allows you to automate your build, test, and deployment pipeline directly within your GitHub repository. You can create workflows that respond to GitHub events like push, pull requests, or issue creation. This feature-rich platform supports a variety of programming languages and frameworks, making it a versatile tool for developers.

Python Example

For Python projects, you can set up a workflow to install dependencies, run tests, and lint your code. Here's a basic `.github/workflows/python.yml` example:

```yaml name: Python CI

on: [push]

jobs:

 build:
   runs-on: ubuntu-latest
   steps:
   - uses: actions/checkout@v2
   - name: Set up Python
     uses: actions/setup-python@v2
     with:
       python-version: '3.8'
   - name: Install dependencies
     run: |
       pip install flake8 pytest
       if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
   - name: Lint with flake8
     run: |
       # stop the build if there are Python syntax errors or undefined names
       flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
       # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
       flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
   - name: Test with pytest
     run: |
       pytest
```

Flask Example

Testing a Flask application involves setting up a workflow to execute tests with pytest or another testing framework. You can adapt the Python example by specifying your Flask-specific dependencies and test commands.

Django Example

For Django projects, the workflow can include steps to set up a database for running tests:

```yaml name: Django CI

on: [push]

jobs:

 build:
   runs-on: ubuntu-latest
   services:
     postgres:
       image: postgres:11
       env:
         POSTGRES_USER: postgres
         POSTGRES_PASSWORD: postgres
       ports:
         - 5432:5432
       # Provide the container time to start before starting the test steps
       options: >-
         --health-cmd pg_isready
         --health-interval 10s
         --health-timeout 5s
         --health-retries 5
   steps:
   - uses: actions/checkout@v2
   - name: Set up Python
     uses: actions/setup-python@v2
     with:
       python-version: '3.8'
   - name: Install dependencies
     run: |
       pip install pipenv
       pipenv install --dev
   - name: Run tests
     env:
       DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
     run: |
       pipenv run python manage.py test
```

JavaScript Example

For projects using JavaScript, you can configure a workflow to install dependencies with npm or yarn and run your test suite:

```yaml name: JavaScript CI

on: [push]

jobs:

 build:
   runs-on: ubuntu-latest
   steps:
   - uses: actions/checkout@v2
   - name: Use Node.js
     uses: actions/setup-node@v1
     with:
       node-version: '12.x'
   - name: Install dependencies
     run: npm install
   - name: Run tests
     run: npm test
```

React Example

React applications, bootstrapped with Create React App, can be tested using a similar workflow to the JavaScript example, using `npm test` or `yarn test` to run the test suite:

```yaml name: React CI

on: [push]

jobs:

 test:
   runs-on: ubuntu-latest
   steps:
   - uses: actions/checkout@v2
   - name: Setup Node.js environment
     uses: actions/setup-node@v2
     with:
       node-version: 14
   - run: npm install
   - run: npm test
```

Vue.js Example

For Vue.js projects, testing can be automated with GitHub Actions by installing project dependencies and executing the test runner:

```yaml name: Vue.js CI

on: [push]

jobs:

 build:
   runs-on: ubuntu-latest
   steps

:

   - uses: actions/checkout@v2
   - name: Setup Node.js
     uses: actions/setup-node@v2
     with:
       node-version: '14'
   - run: npm install
   - run: npm run test:unit
```

TypeScript Example

TypeScript projects often use a build step to compile TypeScript to JavaScript. This can be included in your workflow before running tests:

```yaml name: TypeScript CI

on: [push]

jobs:

 build:
   runs-on: ubuntu-latest
   steps:
   - uses: actions/checkout@v2
   - name: Setup Node.js
     uses: actions/setup-node@v2
     with:
       node-version: '14'
   - run: npm install
   - run: npm run build
   - run: npm test
```

Angular Example

Angular applications can be tested using the Angular CLI's built-in test command. Here’s how you can set up GitHub Actions for an Angular project:

```yaml name: Angular CI

on: [push]

jobs:

 build:
   runs-on: ubuntu-latest
   steps:
   - uses: actions/checkout@v2
   - name: Use Node.js
     uses: actions/setup-node@v1
     with:
       node-version: '12.x'
   - name: Install dependencies
     run: npm install
   - name: Run tests
     run: ng test --watch=false --progress=false --browsers=ChromeHeadlessCI
```

Given the extensive range of languages and frameworks requested, and the space constraints, I'm unable to provide detailed examples for each technology in this format. However, the examples above offer a glimpse into how GitHub Actions can be tailored to fit a wide variety of CI/CD scenarios across different stacks, from Python-based web applications to modern JavaScript frameworks and beyond. For languages and frameworks not covered here, the general approach remains similar: set up the environment, install dependencies, run the build process (if applicable), and execute the test suite.


Snippet from Wikipedia: Continuous integration

In software engineering, continuous integration (CI) is the practice of merging all developers' working copies to a shared mainline several times a day. Nowadays it is typically implemented in such a way that it triggers an automated build with testing. Grady Booch first proposed the term CI in his 1991 method, although he did not advocate integrating several times a day. Extreme programming (XP) adopted the concept of CI and did advocate integrating more than once per day – perhaps as many as tens of times per day.

External Sites

Main

Interesting Articles

Support Resources, FAQs, Q&A, Docs, Blogs

Search Engines

Repos and Registries

Courses

Books

Vidcasts-Podcasts

Software development process

Paradigms and models

Methodologies and frameworks

Supporting disciplines

Practices

Tools

Standards and Bodies of Knowledge

Glossaries

continuous integration (CI) is the practice of merging all developers' working copies to a shared mainline several times a day.<ref name=“martinfowler” /> Grady Booch first proposed the term CI in his 1991 method,<ref>

</ref> although he did not advocate integrating several times a day. Extreme programming (XP) adopted the concept of CI and did advocate integrating more than once per day – perhaps as many as tens of times per day.<ref>

</ref>

Rationale

When embarking on a change, a developer takes a copy of the current code base on which to work. As other developers submit changed code to the source code repository, this copy gradually ceases to reflect the repository code. Not only can the existing code base change, but new code can be added as well as new libraries, and other resources that create dependencies, and potential conflicts.

The longer development continues on a branch without merging back to the mainline, the greater the risk of multiple integration conflicts<ref>

</ref> and failures when the developer branch is eventually merged back. When developers submit code to the repository they must first update their code to reflect the changes in the repository since they took their copy. The more changes the repository contains, the more work developers must do before submitting their own changes.

Eventually, the repository may become so different from the developers' baselines that they enter what is sometimes referred to as “merge hell”, or “integration hell”,<ref name=“Cunningham, Integration Hell”>

</ref> where the time it takes to integrate exceeds the time it took to make their original changes.<ref>

</ref>

Workflows

Run tests locally

CI is intended to be used in combination with automated unit tests written through the practices of test-driven development. This is done by running and passing all unit tests in the developer's local environment before committing to the mainline. This helps avoid one developer's work-in-progress breaking another developer's copy. Where necessary, partially complete features can be disabled before committing, using feature toggles for instance.

Compile code in CI

A build server compiles the code periodically or even after every commit and reports the results to the developers. The use of build servers had been introduced outside the XP (extreme programming) community and many organisations have adopted CI without adopting all of XP.

Run tests in CI

In addition to automated unit tests, organisations using CI typically use a build server to implement continuous processes of applying quality control in general – small pieces of effort, applied frequently. In addition to running the unit and integration tests, such processes run additional static analyses, measure and profile performance, extract and format documentation from the source code and facilitate manual QA processes. On the popular Travis CI service for open-source, only 58.64% of CI jobs execute tests.<ref>

</ref>

This continuous application of quality control aims to improve the quality of software, and to reduce the time taken to deliver it, by replacing the traditional practice of applying quality control after completing all development. This is very similar to the original idea of integrating more frequently to make integration easier, only applied to QA processes.

Deploy an artifact from CI

Now, CI is often intertwined with continuous delivery or continuous deployment in what is called CI/CD pipeline. “Continuous delivery” makes sure the software checked in on the mainline is always in a state that can be deployed to users and “continuous deployment” makes the deployment process fully automated.

History

The earliest known work on continuous integration was the Infuse environment developed by G. E. Kaiser, D. E. Perry, and W. M. Schell.<ref>

</ref>

In 1994, Grady Booch used the phrase continuous integration in Object-Oriented Analysis and Design with Applications (2nd edition)<ref>

</ref> to explain how, when developing using micro processes, “internal releases represent a sort of continuous integration of the system, and exist to force closure of the micro process”.

In 1997, Kent Beck and Ron Jeffries invented Extreme Programming (XP) while on the Chrysler Comprehensive Compensation System project, including continuous integration.<ref name=“martinfowler”>

</ref>

Beck published about continuous integration in 1998, emphasising the importance of face-to-face communication over technological support.<ref>

</ref> In 1999, Beck elaborated more in his first full book on Extreme Programming.<ref name=“Beck, Extreme Programming Explained”>

</ref> CruiseControl, one of the first open-source CI tools,<ref>

</ref>

was released in 2001.

Common practices

This section lists best practices suggested by various authors on how to achieve continuous integration, and how to automate this practice. Build automation is a best practice itself.<ref name=“Brauneis, [OSLC] Possible new Working Group - Automation”>

</ref><ref name=“Taylor, Rails Deployment and Automation with ShadowPuppet and Capistrano”>

</ref>

Continuous integration – the practice of frequently integrating one's new or changed code with the existing code repository – should occur frequently enough that no intervening window remains between commit and build, and such that no errors can arise without developers noticing them and correcting them immediately.<ref name=“martinfowler” /> Normal practice is to trigger these builds by every commit to a repository, rather than a periodically scheduled build. The practicalities of doing this in a multi-developer environment of rapid commits are such that it is usual to trigger a short time after each commit, then to start a build when either this timer expires, or after a rather longer interval since the last build. Note that since each new commit resets the timer used for the short time trigger, this is the same technique used in many button debouncing algorithms.<ref>See for example

</ref> In this way the commit events are “debounced” to prevent unnecessary builds between a series of rapid-fire commits. Many automated tools offer this scheduling automatically.

Another factor is the need for a version control system that supports atomic commits, i.e. all of a developer's changes may be seen as a single commit operation. There is no point in trying to build from only half of the changed files.

To achieve these objectives, continuous integration relies on the following principles.

Maintain a code repository

This practice advocates the use of a revision control system for the project's source code. All artifacts required to build the project should be placed in the repository. In this practice and in the revision control community, the convention is that the system should be buildable from a fresh checkout and not require additional dependencies. Extreme Programming advocate Martin Fowler also mentions that where branching is supported by tools, its use should be minimised.<ref name=“Fowler, Continuous Integration practices”>

</ref> Instead, it is preferred for changes to be integrated rather than for multiple versions of the software to be maintained simultaneously. The mainline (or trunk) should be the place for the working version of the software.

Automate the build

A single command should have the capability of building the system. Many build tools, such as make, have existed for many years. Other more recent tools are frequently used in continuous integration environments. Automation of the build should include automating the integration, which often includes deployment into a production-like environment. In many cases, the build script not only compiles binaries, but also generates documentation, website pages, statistics and distribution media (such as Debian DEB, Red Hat RPM or Windows MSI files).

Make the build self-testing

Once the code is built, all tests should run to confirm that it behaves as the developers expect it to behave.<ref>

</ref>

Everyone commits to the baseline every day

By committing regularly, every committer can reduce the number of conflicting changes. Checking in a week's worth of work runs the risk of conflicting with other features and can be very difficult to resolve. Early, small conflicts in an area of the system cause team members to communicate about the change they are making.<ref name=“:0”>

</ref> Committing all changes at least once a day (once per feature built) is generally considered part of the definition of Continuous Integration. In addition performing a nightly build is generally recommended.

These are lower bounds; the typical frequency is expected to be much higher.

Every commit (to baseline) should be built

The system should build commits to the current working version to verify that they integrate correctly. A common practice is to use Automated Continuous Integration, although this may be done manually. Automated Continuous Integration employs a continuous integration server or daemon to monitor the revision control system for changes, then automatically run the build process.

Every bug-fix commit should come with a test case

When fixing a bug, it is a good practice to push a test case that reproduces the bug. This avoids the fix to be reverted, and the bug to reappear, which is known as a regression. Researchers have proposed to automate this task: if a bug-fix commit does not contain a test case, it can be generated from the already existing tests.<ref>

</ref>

Keep the build fast

The build needs to complete rapidly, so that if there is a problem with integration, it is quickly identified.

Test in a clone of the production environment

Having a test environment can lead to failures in tested systems when they deploy in the production environment because the production environment may differ from the test environment in a significant way. However, building a replica of a production environment is cost prohibitive. Instead, the test environment, or a separate pre-production environment (“staging”) should be built to be a scalable version of the production environment to alleviate costs while maintaining technology stack composition and nuances. Within these test environments, service virtualisation is commonly used to obtain on-demand access to dependencies (e.g., APIs, third-party applications, services, mainframes, etc.) that are beyond the team's control, still evolving, or too complex to configure in a virtual test lab.

Make it easy to get the latest deliverables

Making builds readily available to stakeholders and testers can reduce the amount of rework necessary when rebuilding a feature that doesn't meet requirements. Additionally, early testing reduces the chances that defects survive until deployment. Finding errors earlier can reduce the amount of work necessary to resolve them.

All programmers should start the day by updating the project from the repository. That way, they will all stay up to date.

Everyone can see the results of the latest build

It should be easy to find out whether the build breaks and, if so, who made the relevant change and what that change was.

Automate deployment

Most CI systems allow the running of scripts after a build finishes. In most situations, it is possible to write a script to deploy the application to a live test server that everyone can look at. A further advance in this way of thinking is continuous deployment, which calls for the software to be deployed directly into production, often with additional automation to prevent defects or regressions.<ref>

</ref><ref>

</ref>

Costs and benefits

Continuous integration is intended to produce benefits such as:

  • Integration bugs are detected early and are easy to track down due to small change sets. This saves both time and money over the lifespan of a project.
  • Avoids last-minute chaos at release dates, when everyone tries to check in their slightly incompatible versions
  • When unit tests fail or a bug emerges, if developers need to revert the codebase to a bug-free state without debugging, only a small number of changes are lost (because integration happens frequently)
  • Constant availability of a “current” build for testing, demo, or release purposes
  • Frequent code check-in pushes developers to create modular, less complex code

With continuous automated testing benefits can include:

  • Enforces discipline of frequent automated testing
  • Immediate feedback on system-wide impact of local changes
  • Software metrics generated from automated testing and CI (such as metrics for code coverage, code complexity, and feature completeness) focus developers on developing functional, quality code, and help develop momentum in a team

Some downsides of continuous integration can include:

  • Constructing an automated test suite requires a considerable amount of work, including ongoing effort to cover new features and follow intentional code modifications.
  • There is some work involved to set up a build system, and it can become complex, making it difficult to modify flexibly.<ref>

    </ref>

  • Continuous integration is not necessarily valuable if the scope of the project is small or contains untestable legacy code.
  • Value added depends on the quality of tests and how testable the code really is.<ref name=“:1”>

    </ref>

  • Larger teams means that new code is constantly added to the integration queue, so tracking deliveries (while preserving quality) is difficult and builds queueing up can slow down everyone.<ref name=“:1” />
  • With multiple commits and merges a day, partial code for a feature could easily be pushed and therefore integration tests will fail until the feature is complete.<ref name=“:1” />
  • Safety and mission-critical development assurance (e.g., DO-178C, ISO 26262) require rigorous documentation and in-process review that are difficult to achieve using continuous integration. This type of life cycle often requires additional steps be completed prior to product release when regulatory approval of the product is required.

See also

References

continuous_integration_ci.txt · Last modified: 2024/03/14 18:42 by 127.0.0.1