Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,12 @@ $(RELEASE_AAB): version gradle-dependencies
(cd android && ./gradlew test bundleRelease)
install -C ./android/build/outputs/bundle/release/android-release.aab $@

# PLATFORM=tv signals to gradle that we should build for AndroidTV. To
# distinguish the TV variant from the phone/tablet build in the Play Store,
# we temporarily increment the versionCode in android/build.gradle by 1 for
# the duration of the build, then restore the original value via a shell trap
# PLATFORM=tv signals to gradle that we should build for AndroidTV. The stamped
# versionCode reserves its last digit for the variant: phone/tablet builds end
# in 0 and TV builds end in 1, so the two are distinguishable in the Play Store.
# build.gradle keeps a bare integer literal (external tooling greps it), so we
# add the +1 here: temporarily increment the versionCode in android/build.gradle
# for the duration of the build, then restore the original value via a shell trap
# so the working tree is left clean even if the gradle build fails.
$(RELEASE_TV_AAB): version gradle-dependencies
@echo "Building TV release AAB"
Expand Down Expand Up @@ -310,14 +312,25 @@ bumposs: update-oss tailscale.version bump-version-code
source tailscale.version && git commit -sm "android: bump OSS" -m "OSS and Version updated to $${VERSION_LONG}" go.toolchain.rev android/build.gradle go.mod go.sum
source tailscale.version && git tag -a "$${VERSION_LONG}" -m "OSS and Version updated to $${VERSION_LONG}"

# Recomputes the base versionCode from tailscale.version and rewrites the
# `versionCode <n>` line in android/build.gradled
# Stamps android/build.gradle's versionCode from wall-clock time: minutes since
# the Unix epoch, times 10. Time is a global, monotonically increasing authority,
# so releases cut from different branches never collide or regress (see the
# versionCode comment in android/build.gradle). The last digit is reserved for
# the build variant; the AndroidTV build adds 1 at build time. If the machine
# clock would produce a value not strictly greater than the current one (clock
# skew, or two bumps within the same minute), fall back to bumping the current
# value by 10 so the code always advances.
.PHONY: bump-version-code
bump-version-code: tailscale.version
@source tailscale.version && \
BASE_VERSION_CODE=$$((VERSION_MAJOR * 100000000 + VERSION_MINOR * 100000 + VERSION_PATCH * 10)) && \
echo "Setting android/build.gradle versionCode to $$BASE_VERSION_CODE" && \
sed -i.bak -E "s/versionCode [0-9]+/versionCode $$BASE_VERSION_CODE/" android/build.gradle && \
bump-version-code:
@CUR_VERSION_CODE=$$(grep -oE 'versionCode [0-9]+' android/build.gradle | awk '{print $$2}') && \
TIME_VERSION_CODE=$$(( $$(date +%s) / 60 * 10 )) && \
if [ "$$TIME_VERSION_CODE" -gt "$$CUR_VERSION_CODE" ]; then \
NEXT_VERSION_CODE=$$TIME_VERSION_CODE; \
else \
NEXT_VERSION_CODE=$$((CUR_VERSION_CODE + 10)); \
fi && \
echo "Setting android/build.gradle versionCode $$CUR_VERSION_CODE -> $$NEXT_VERSION_CODE" && \
sed -i.bak -E "s/versionCode [0-9]+/versionCode $$NEXT_VERSION_CODE/" android/build.gradle && \
rm android/build.gradle.bak

.PHONY: update-oss ## Update the tailscale.com go module
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,11 @@ make install

## Building a release

Use `make tag_release` to bump the Android version code, update the version
name, and tag the current commit.
Use `make tag_release` to stamp the Play Store version code, update the version
name, and tag the current commit. The version code is derived from wall-clock
time (minutes since the Unix epoch) at release time and committed into
`android/build.gradle`, so it increases monotonically across all builds and
branches while staying fixed for any given commit.

We only guarantee to support the latest Go release and any Go beta or
release candidate builds (currently Go 1.14) in module mode. It might
Expand Down
22 changes: 17 additions & 5 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,23 @@ android {
defaultConfig {
minSdkVersion 26
targetSdkVersion androidApiLevel
// versionCode is written here by `make bumposs` / `make tag_release`
// (base = major*100000000 + minor*100000 + patch*10). AndroidTV builds
// increment this by 1 in the Makefile's release-tv target so the two
// variants are distinguishable in the Play Store.
versionCode 110300150
// versionCode is stamped here by `make bump-version-code` (run via
// `make bumposs` / `make tag_release`) from wall-clock time: minutes
// since the Unix epoch, times 10. Time is a global, monotonically
// increasing authority, so releases cut from different branches never
// collide or go backwards -- unlike a counter stored in this file, which
// each branch would bump independently. (The Play Store requires
// versionCode to strictly increase across uploads, and stable point
// releases ship after higher-numbered unstable builds, so anything
// version-derived or per-branch eventually regresses.)
//
// This MUST stay a bare `versionCode <integer>` literal with no
// surrounding logic: external build tooling greps this line and parses
// the number directly. The last digit is reserved for the build variant;
// the Makefile's release-tv target rewrites this integer to end in 1 for
// AndroidTV builds so phone (...0) and TV (...1) uploads stay
// distinguishable in the Play Store.
versionCode 297588040
versionName getVersionProperty("VERSION_LONG")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Expand Down
Loading