Skip to content

Administrator Guidelines

Artem Bilan edited this page Apr 8, 2021 · 39 revisions

These instructions are only relevant to those who have been granted push rights on the upstream repository (those who are in the spring-integration-admin group). Contributors, even admin group members when contributing code, should consult the [Contributor Guidelines](Contributor Guidelines).

Merging Pull Requests

The following steps indicate a typical merge of a Pull Request once its review is complete and it has been approved by at least one team member (other than the original contributor). Note that the button on github can also merge a PR (our comment below emulates the comment it would generate), but while that will only be enabled if the PR can merge cleanly, it will not check if the PR is up-to-date with respect to upstream/main. In order to maintain a clean linear history (with only merge commits being non-linear), the following steps include a rebase (and optionally, an interactive squashing rebase as well).

// sync up
git fetch --all

// make sure your local main is up to date
git checkout main
git merge upstream/main

// grab the branch for the PR
git checkout --track johndoe/INT-123 

// make sure that branch is up-to-date
git rebase main

// get a quick view of the number of commits past upstream/main
git log --oneline

// At this point, you might even do some basic polishing, but typically
// that should be handled by the original committer via PR feedback.
// - Check copyright dates
// - Include a check for whitespace violations and fix or bounce back to contributor.
git log -p --check

// IF you want to squash (no historical value) do an interactive rebase;
// 3 in this case (HEAD~3) being an example number of commits to squash.
git rebase -i HEAD~3

// Polish the comment if necessary during the interactive rebase

// Do a full build
./gradlew build

// go back to the local main
git checkout main

// perform a fast-forward merge from the local tracking branch
git merge INT-123 --ff-only

// verify that the commit log is linear (the --ff-only should prevent non-linear merges)
git log --graph --pretty=oneline

// push to your own fork's main
git push origin main

// push to THE upstream main
git push upstream main

To avoid accidental merge commits, you can configure git to always use fast-forward on main...

git config branch.main.mergeoptions "--ff-only"

Sometimes, however, if there are a number of commits on a topic branch and it is desirable to keep them separate, then use a non-fast-forward merge instead (but you will have to remove the mergeoptions above).

// merge the local tracking branch into main with a comment having this format (and no fast-forward)
git merge -m "Merge pull request #99 from johndoe/INT-123" --log --no-ff INT-123

// polish the results of the previous --log if necessary
git commit --amend

// push to your own fork's main
git push origin main

// push to THE upstream main
git push upstream main

After the branch has been merged, if that branch did require rebasing main, then it will not be automatically closed within github. If that's the case, manually close the PR in github, optionally including a comment. GitHub will close the PR if no rebase was required, but you should check the PR list anyway.

Common Questions

  1. What if my push to upstream main fails after I've merged the branch into my local main? This can occur if someone else has pushed another PR to the upstream main after your last rebase on the branch.
    The solution is as follows:
// Update your main branch
git fetch --all

//Reset the index and working tree to remote. 
git reset --hard upstream/main

// Go back to your branch
git checkout INT-123

// Rebase the branch to include all changes
git rebase main

// Do a full build
./gradlew build

// go back to the local main
git checkout main

// perform a fast-forward merge from the local tracking branch
git merge INT-123 --ff-only

// verify that the commit log is linear (the --ff-only should prevent non-linear merges)
git log --graph --pretty=oneline

// push to your own fork's main
git push origin main

// push to THE upstream main
git push upstream main

Warning: Any changes to tracked files in the local main since <commit> are discarded.

Release Process

The steps are simple, and almost everything is done via the Bamboo and Artifactory UIs.

One-time setup

Configure your CI build plan to use the Artifactory Maven 3 or Artifactory Gradle tasks as appropriate. For "Deployer Username", use "buildmaster" (password on request).

Steps at a glance

  1. Stage the release into the libs-staging-local repository
  2. Verify and test the staged artifacts
  3. Promote the release to libs-milestone-local (or libs-release-local as appropriate).
  4. Merge release branch
  5. Announce the release

Steps in detail

1. Stage the release

The Artifactory Bamboo plugin mentioned above also includes sophisticated Release Management capabilities. This feature allows for publishing releases directly from CI, including creating a release branch and/or tag; incrementing the project version; and publishing to the libs-staging-local, libs-milestone-local or libs-release-local repositories as appropriate.

To access this feature, click on the "Default Job" for the Main build plan (as an example), where you'll see a link to "Artifactory Release Management". Fill out the form fields there and click "Build and Release to Artifactory". Typical values -- in this case for a milestone release -- look something like the following:

In the example above, the version property key refers to the property of the same name declared in the gradle.properties in the root of the source tree. This value will actually be modified and updated in source control during the release process.

Using a 'release branch' is optional and Spring Integration Team doesn't use this feature for their release. This means that updates to the gradle.properties file will occur on a branch named 4.3.2.RELEASE otherwise, helping to isolate the release from changes on the main branch, and also allowing for simplified rollback in case a last minute change needs to be made after staging the release. But Spring Integration Team doesn't mind to have such a commit history on main during release process.

Create VCS Tag is checked and required, indicating that a git tag named v4.3.2.RELEASE should be created, pointing to the commit where the version property is incremented.

Notice that 'Next development version comment' refers to the next 4.3.3.BUILD-SNAPSHOT version. For the Milestone release (e.g. 5.0.0.M1) the 'Next integration value' of the version property is configured to return to it's previous value of 5.0.0.BUILD-SNAPSHOT if it is left blank. The tooling is smart enough here to avoid creating an additional commit, so no comment is necessary.

Importantly, notice that we're publishing to the libs-staging-local repository - this is just what it sounds like: a staging area that allows us to test out the release internally before finally promoting it to the actual libs-milestone-local (or libs-release-local as appropriate) repository and announcing it to the world.

With these values supplied, click 'Build and Release to Artifactory'.

2. Verify staged artifacts

When the staging build and release process is complete, you can navigate to the associated build record in Artifactory to verify that all modules were published as expected. Use libs-staging-local repository in tree to expand directories for your artifacts.

You may also wish to have internal team members 'smoke test' the release, e.g. change their sample projects and dependent framework builds to point to http://repo.spring.io/libs-staging-local and compile/test/run against the staged artifacts.

3. Promote the release

When verification is complete, return to the build in Bamboo from which you staged the release and click 'Default Job' and 'Artifactory' at the top, below the Job status bar. Make sure you have the side-bar shown in order to see this. You'll now see 'Promotion' options as follows:

The 'Target promotion repository' should be set to 'libs-milestone-local' for milestones and 'libs-release-local' for RELEASE versions respectively. Click 'Update' to move all artifacts from 'libs-staging-local' to 'libs-milestone-local'/'libs-release-local'.

IMPORTANT: Any release should go through the "Normal" promotion mode. "Bintray and Central" doesn't work after some Bamboo and Artifactory upgrade.

See Publishing artifacts to Maven Central

4. Merge the release branch

NOTE: Spring Integration doesn't use release branch concept, so the rest of this paragraph is just for an information. For example Spring Framework process.

At this point, the release is complete and successful, so the release branch should be merged back into main, e.g.

$ cd spring-framework              # your local spring-framework working copy
$ git checkout main
$ git fetch --all                  # to fetch the branch created during the release
$ git merge springsource/main    # make sure you're up to date
$ git merge springsource/3.2.0.M1  # assuming your remote is named 'springsource'
$ vi gradle.properties             # bump the version to 3.1.0.BUILD-SNAPSHOT
$ git ci -am"Increment version to 3.2.0.BUILD-SNAPSHOT"
$ git push springsource main:main

5. Announce the release!

At this point, announcements may be made and users may consume the released artifacts by adding http://repo.spring.io/milestone (or http://repo.spring.io/release, respectively) to their build scripts.

Publishing artifacts to Maven Central

Since automatic release promotion doesn't work (yet), we have to follow with REST API instructions from JFrog or use Artifactory and Bintray UIs to perform required actions.

After promoting release to the libs-release-local we have to distribute release build through the distribution repository in the Artifactory.

Spring standard provide two types of distribution repositories

  • spring-distributions - when all artifacts in the same Maven group will be present on the Bintray in the same package, for example spring-integration project artifacts: https://bintray.com/spring/jars/org.springframework.integration

  • spring-train-distributions - when artifacts in the same Maven group have different version and different release, cycles. For example spring-integration-extensions projects or Spring Data modules.

For this purpose we have to find an appropriate release build in the Artifactory Build Browser after Normal promotion from Bamboo. For example Spring Kafka 1.0.3.RELEASE:

From here we can just push the Distribute button on the right side or perform an appropriate Artifactory REST API command:

curl -i -u buildmaster:<password> -XPOST "https://repo.spring.io/api/build/distribute/Spring%20Kafka%20-%201.0.x%20-%20Default%20Job/16" -H "Content-Type: application/json" -d "{\"sourceRepos\": [\"libs-release-local\"], \"targetRepo\": \"spring-distributions\", \"dryRun\": \"true\"}"

From here we have to know buildmaster password or just use your own Artifactory credentials if you have an appropriate distribution permissions.

In both case we should properly choose spring-distributions or spring-train-distributions distribution repository according to our release artifact(s). The Dry Run lets us to check if our release is correct and we really have proper permissions to perform the command. In the end of command we have some errors indicating that some of our artifacts aren't feasible for Maven distribution. In the lucky case they are zip files for documentation, XSD schemas and the entire distribution. But that is worth to check all the error messages:

If all errors are just only about zip files, we can go ahead with real distribution to the Bintray. In the end we have the same zip error, which is normal, but we has to go to the Bintray to find our artifacts. For example aforementioned Spring Kafka 1.0.3.RELEASE:

To synchronize release artifacts into the Maven Central we can perform an appropriate Bintray REST command or use Bintray Maven Central Sync UI:

In both cases we need to know Sonetype User token key and User token password credentials to perform the operation.

Synchronization to Maven Central should be complete within three hours of pressing the 'release' button. In practice, it is usually two hours or less, but with just the right timing (or wrong timing as the case may be), you may need to wait the full three.