Persist environment variables (step outputs) through builds

A very useful feature would be the ability to persist some variables through builds. For example, if my last build was Android version 1.0.1, I don’t want to build again (and notify my Slack tester channel) until the version is bumped to 1.0.2. I would like to store a persistent variable, e.g. LAST_VERSION_NAME, and check against that with a bash script at the start of each build. Any way to do this with current build steps / does this seem like a reasonable feature to implement?

Great idea, thank you for the #feature-request @insidelabs!

You might be able to do this with the Build Cache - just add the Cache:Pull and Cache:Push steps to your workflow (cache:pull will download the cache if available, and cache:push will update/upload it if required - if any file changes), and if you don’t change the configurations (what to cache), you can just write into the $BITRISE_CACHE_DIR directory and that will persist between builds.

An important note though (highlight from the Build Cache docs):

If you write into the cache on a feature/ branch, that will only be available on that specific branch. E.g. the cache of feature/a won’t be available for feature/b, but will be available for every subsequent build of feature/a (until the cache expires, if you don’t use it for a while).

The only exception is the cache generated by the “primary” branch (the one you set on the Settings tab as the primary branch). If feature/c doesn’t have a cache yet, it will get the cache of the “primary” branch until it writes into its own cache.

The build on a non default branch, to speed up things, can (read-only) access the primary branch’s cache, until a successful build on the new branch. Once a build on the new branch pushes a cache, new builds on that branch will get the branch’s cache. Caches are stored and available for every branch separately.

This is quite useful for regular dependencies, as you most likely want to utilize the default/primary branch’s cache when you start a new branch, but in your case you have to be aware of this. Of course this can be useful too, to not to send notifications from “feature/” branches until you bump the version number.

If you want to handle this case, that the cache is for the primary branch, you can e.g. write the current build’s $BITRISE_GIT_BRANCH into the cache file, and then compare it in the Script with that build’s $BITRISE_GIT_BRANCH. If that’s the same, then the cache was generated by the branch. If it’s not the same, then the cache was generated by the primary/default branch and you can decide how you want to handle it (e.g. ignore it).

If you have any questions, just let us know!

Happy Building! :slight_smile:

1 Like

Thanks! I think I’ll be able to do what I need with the Cache steps :slight_smile:

1 Like

Hi @insidelabs & @viktorbenei,

i do not really see the use case of this feature.

You can define multiple workflows to separate what to do during your automations.

For example, if your are working on develop branch and you want to test the changes on this branch, you should setup a ci workflow, which runs your tests and triggered by a push/pr on develop branch.

Once you finish a major feature and you want to let your testers to test it, you may push your changes on master branch, which triggers another workflow (primary for example), which runs your tests, generates the artifact to test and notify your testers. So primary workflow would be triggered by push/pr on master or even by tagging your source code’s current state.

Once your are ready for release your app, you may push your changes to the release branch, which triggers a workflow (for example release), which runs your tests and deploys your artifact.

So to separate tasks to be done based on your source code’s state, i recommend to define multiple workflows, instead of using persistent variables.

1 Like

True, I definitely agree that if you can use multiple workflows that’s a way better solution, just wanted to mention that in case you actually need a persistent storage between builds, the cache can be utilized (but limitations have to be considered of course).

With react native the release strategy is a lot more complicated. If there are native changes you do a binary update if not you do a code push and periodically you do a binary update with the latest js code. For releases this could be achieved with a complex branching strategy but there would be no way to have an alpha build that just fallows the develop branch. You could compare files with the last commit but that only works if the last commit was deployed. It would be much easier if there was a way to persist the commit id when the build is deployed.

@respectTheCode could you please share a bit more info about this? I might have missed something, but I think this could be done through the caching method described above: Persist variables through builds

I have a similar usecase in which different flows can not help in any way. Basically, when we deploy apps in the GooglePlay, we start the rollout with a small percentage of users (2%) and then every day increase it gradually (5, 10, 20, 50, 100). I have done a step in bitrise that every night checks what was the last percentage, and increase it to the next step. However, since GooglePlay does not provide a way to read it (only to set it), the only way remaining is to store that info as part of the workflow run. So, basically, when the build is submitted I store a file with a 2%, then every day the workflow checks the last number, increase it and save it back for the next day.

I have been trying to make it with cache push/pull, and at first it seemed to work, but I am seeing that every now and then it fails, basically having no previous data in the cache, so it resets my rollout back to 2%. Any idea why the cache expires or how to avoid it? I would like it to be “persistent” at least for 1 week, or have some other kind of storage for this (persisting variables, files or whatever)