> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Get more control over your environments with build variables

> Discover the visible-build flag on Platform.sh, enabling environment-specific build variables for more control over your development process.

export const PostMeta = ({data = {}}) => {
  const {author, date, image} = data;
  const authors = Array.isArray(author) ? author : author ? [author] : [];
  const resolveAuthor = slug => {
    const entry = AUTHOR_MAP[slug] || ({});
    const name = entry.name || slug;
    const github = entry.github || null;
    const linkedin = entry.linkedin || null;
    const url = github ? `https://github.com/${github}` : linkedin || null;
    const avatarUrl = github ? `https://github.com/${github}.png?size=64` : null;
    return {
      name,
      url,
      avatarUrl
    };
  };
  const formattedDate = date ? new Date(date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }) : null;
  if (!image && authors.length === 0 && !formattedDate) return null;
  const AUTHOR_MAP = {
    "aaron-collier": {
      "name": "Aaron Collier"
    },
    "aaron-dudenhofer": {
      "name": "Aaron Dudenhofer"
    },
    "aaron-porter": {
      "name": "Aaron Porter"
    },
    "adriaan-odendaal": {
      "name": "Adriaan Odendaal"
    },
    "ajmal": {
      "name": "Ajmal Siddiqui"
    },
    "akalipetis": {
      "name": "Antonis Kalipetis"
    },
    "alexander-varwijk": {
      "name": "Alexander Varwijk"
    },
    "alicia-bevilacqua": {
      "name": "Alicia Bevilacqua"
    },
    "amelie-deguerry": {
      "name": "Amelie Deguerry"
    },
    "anacidre": {
      "name": "Ana Cidre",
      "linkedin": "https://www.linkedin.com/in/ana-cidre"
    },
    "andoni": {
      "name": "Andoni Auzmendi"
    },
    "andrei-taranu": {
      "name": "Andrei (Alex) Taranu",
      "linkedin": "https://www.linkedin.com/in/andrei-alex-taranu/"
    },
    "andrew-baxter": {
      "name": "Andrew Baxter"
    },
    "andrew-melck": {
      "name": "Andrew Melck"
    },
    "antoine-crochet-damais": {
      "name": "Antoine Crochet Damais"
    },
    "augustin-delaporte": {
      "name": "Augustin Delaporte",
      "linkedin": "https://www.linkedin.com/in/augustindelaporte/"
    },
    "branislav-bujisic": {
      "name": "Branislav Bujisic"
    },
    "carl-smith": {
      "name": "Carl Smith"
    },
    "caroline-leroy": {
      "name": "Caroline Leroy"
    },
    "cati-mayer": {
      "name": "Cati Mayer"
    },
    "catplat": {
      "name": "C Trinkwon"
    },
    "ceelolulu": {
      "name": "Celeste van der Watt"
    },
    "chadwcarlson": {
      "name": "Chad Carlson",
      "github": "chadwcarlson",
      "linkedin": "https://www.linkedin.com/in/chadwcarlson"
    },
    "chris-ward": {
      "name": "Chris Ward"
    },
    "chris-yates": {
      "name": "Chris Yates"
    },
    "christian-sieber": {
      "name": "Christian Sieber"
    },
    "christopher-lockheardt": {
      "name": "Christopher Lockheardt"
    },
    "christopher-skene": {
      "name": "Christopher Skene"
    },
    "chuck-morgan": {
      "name": "Chuck Morgan"
    },
    "corey-dockendorf": {
      "name": "Corey Dockendorf"
    },
    "crell": {
      "name": "Crell"
    },
    "damz": {
      "name": "Damz"
    },
    "dan-morrison": {
      "name": "Dan Morrison"
    },
    "davidbonachera": {
      "name": "David Bonachera",
      "github": "davidbonachera",
      "linkedin": "https://www.linkedin.com/in/davidbonachera"
    },
    "dereliahmet1": {
      "name": "Ahmet Faruk Dereli"
    },
    "devicezero": {
      "name": "Jonas Kröger",
      "github": "devicezero",
      "linkedin": "https://www.linkedin.com/in/jonaskroeger/"
    },
    "doug-goldberg": {
      "name": "Doug Goldberg"
    },
    "duncan-naves": {
      "name": "Duncan Naves",
      "github": "duncannaves",
      "linkedin": "https://www.linkedin.com/in/duncan-naves-a94423aa"
    },
    "erika-bustamante": {
      "name": "Erika Bustamante"
    },
    "fabpot": {
      "name": "Fabien Potencier"
    },
    "flovntp": {
      "name": "Florent Huck",
      "github": "flovntp",
      "linkedin": "https://www.linkedin.com/in/florenthuck"
    },
    "fred-plais": {
      "name": "Fred Plais"
    },
    "gauthier-garnier": {
      "name": "Gauthier Garnier"
    },
    "gilzow": {
      "name": "Paul Gilzow"
    },
    "gmoigneu": {
      "name": "Guillaume Moigneu",
      "github": "gmoigneu",
      "linkedin": "https://www.linkedin.com/in/guillaumemoigneu/"
    },
    "gregqualls": {
      "name": "Greg Qualls"
    },
    "guguss": {
      "name": "Augustin Delaporte"
    },
    "haylee-millar": {
      "name": "Haylee Millar"
    },
    "ivana-kotur": {
      "name": "Ivana Kotur"
    },
    "jackrabbithanna": {
      "name": "Mark Hanna"
    },
    "jared-wright": {
      "name": "Jared Wright",
      "github": "jww-sh",
      "linkedin": "https://www.linkedin.com/in/jaredwaynewright"
    },
    "jessica-orozco": {
      "name": "Jessica Orozco"
    },
    "joey-stanford": {
      "name": "Joey Stanford"
    },
    "john-grubb": {
      "name": "John Grubb"
    },
    "jonas-kruger": {
      "name": "Jonas Kruger"
    },
    "kathryn-frazer": {
      "name": "Kathryn Frazer"
    },
    "kemiojo": {
      "name": "Kemi Elizabeth Ojogbede"
    },
    "kieronsambrook-smith": {
      "name": "Kieronsambrook Smith"
    },
    "laurent-arnoud": {
      "name": "Laurent Arnoud",
      "linkedin": "https://www.linkedin.com/in/laurent-arnoud-861b44121/"
    },
    "letoya-boyne": {
      "name": "Letoya Boyne"
    },
    "lolautruche": {
      "name": "Jérôme Vieilledent"
    },
    "lyly-lepinay": {
      "name": "Lyly Lepinay"
    },
    "manauwar-alam": {
      "name": "Manauwar Alam"
    },
    "marc-antoine-porri": {
      "name": "Marc Antoine Porri"
    },
    "maria-antinkaapo": {
      "name": "Maria Antinkaapo"
    },
    "maria-de-anton": {
      "name": "Maria De Anton"
    },
    "mark-dorison": {
      "name": "Mark Dorison"
    },
    "markus-hausammann": {
      "name": "Markus Hausammann"
    },
    "mary-thomas": {
      "name": "Mary Thomas"
    },
    "mathias-bolt-lesniak": {
      "name": "Mathias Bolt Lesniak"
    },
    "mathieu-strauch": {
      "name": "Mathieu Strauch"
    },
    "matthias-van-woensel": {
      "name": "Matthias Van Woensel",
      "linkedin": "https://www.linkedin.com/in/matthias-van-woensel-267a069"
    },
    "michael-sharp": {
      "name": "Michael Sharp"
    },
    "mupsi": {
      "name": "Marine Gandy"
    },
    "natalie-harper": {
      "name": "Natalie Harper"
    },
    "ngommenginger": {
      "name": "Nicolas Gommenginger",
      "linkedin": "https://www.linkedin.com/in/nicolas-gommenginger"
    },
    "nicholas-bennison": {
      "name": "Nicholas Bennison"
    },
    "nicholas-vahalik": {
      "name": "Nicholas Vahalik"
    },
    "nick-hardiman": {
      "name": "Nick Hardiman"
    },
    "nickanderegg": {
      "name": "Nickanderegg"
    },
    "nicolas-grekas": {
      "name": "Nicolas Grekas",
      "github": "nicolas-grekas",
      "linkedin": "https://www.linkedin.com/in/nicolasgrekas/"
    },
    "niti-malwade": {
      "name": "Niti Malwade"
    },
    "opensocialteam": {
      "name": "Opensocialteam"
    },
    "ori-pekelman": {
      "name": "Ori Pekelman"
    },
    "otavio-santana": {
      "name": "Otavio Santana"
    },
    "palwandi": {
      "name": "Pawan Alwandi",
      "github": "pawpy",
      "linkedin": "https://www.linkedin.com/in/pawanalwandi"
    },
    "patrick-boest": {
      "name": "Patrick Boest"
    },
    "patrick-dawkins": {
      "name": "Patrick Dawkins",
      "github": "pjcdawkins",
      "linkedin": "https://www.linkedin.com/in/patrickdawkins"
    },
    "patrick-klima": {
      "name": "Patrick Klima"
    },
    "pjcdawkins": {
      "name": "Pjcdawkins"
    },
    "prineet-kaurbhurji": {
      "name": "Prineet Kaurbhurji"
    },
    "quentin-sinig": {
      "name": "Quentin Sinig"
    },
    "ralt": {
      "name": "Florian Margaine",
      "github": "ralt",
      "linkedin": "https://www.linkedin.com/in/florian-margaine-43971136"
    },
    "ramanathanramakrishnamurthy": {
      "name": "Ramanathanramakrishnamurthy"
    },
    "remi-lejeune": {
      "name": "Rémi Lejeune"
    },
    "ribel": {
      "name": "Taras Kruts"
    },
    "robert-douglass": {
      "name": "Robert Douglass"
    },
    "rudy-weber": {
      "name": "Rudy Weber"
    },
    "ryan-hicks": {
      "name": "Ryan Hicks"
    },
    "sabri-helal": {
      "name": "Sabri Helal"
    },
    "savannah-bergeron": {
      "name": "Savannah Bergeron"
    },
    "shannon-vettes": {
      "name": "Shannon Vettes"
    },
    "shawn-ogasawara": {
      "name": "Shawn Ogasawara",
      "linkedin": "https://www.linkedin.com/in/shawn-ogasawara-83a9a0/"
    },
    "shawna-spoor": {
      "name": "Shawna Spoor"
    },
    "shedrack-akintayo": {
      "name": "Shedrack Akintayo"
    },
    "simon-ruggier": {
      "name": "Simon Ruggier"
    },
    "sophie-van-der-kindere": {
      "name": "Sophie Van Der Kindere"
    },
    "stefanos-thampis": {
      "name": "Stefanos Thampis"
    },
    "stephen-weinberg": {
      "name": "Stephen Weinberg"
    },
    "sukhman-virk": {
      "name": "Sukhman Virk"
    },
    "sumaira-nazir": {
      "name": "Sumaira Nazir"
    },
    "sumer": {
      "name": "Sümer Cip"
    },
    "syed-raza": {
      "name": "Syed Raza"
    },
    "tamara-bacchia": {
      "name": "Tamara Bacchia"
    },
    "tara-arnold": {
      "name": "Tara Arnold"
    },
    "theosakamg": {
      "name": "Mickael Gaillard",
      "github": "theosakamg"
    },
    "thomasdiluccio": {
      "name": "Thomas di Luccio"
    },
    "tim-anderson": {
      "name": "Tim Anderson"
    },
    "tom-helmer-hansen": {
      "name": "Tom Helmer Hansen"
    },
    "tylermills": {
      "name": "Tyler Mills"
    },
    "upsun": {
      "name": "Upsun"
    },
    "veronika-tolkachova": {
      "name": "Veronika Tolkachova",
      "linkedin": "https://www.linkedin.com/in/veronika-tolkachova-169167a2"
    },
    "vince-parker": {
      "name": "Vince Parker"
    },
    "vinnie-russo": {
      "name": "Vincenzo Russo"
    },
    "vrobert78": {
      "name": "Vincent Robert",
      "github": "vrobert78",
      "linkedin": "https://www.linkedin.com/in/vincent-robert-498a883"
    },
    "yuriy-babenko": {
      "name": "Yuriy Babenko"
    },
    "yuriy-gerasimov": {
      "name": "Yuriy Gerasimov"
    }
  };
  return <div className="post-meta">
      {(authors.length > 0 || formattedDate) && <div className="post-meta-info">
          {authors.length > 0 && <div className="post-meta-authors">
              {authors.map(slug => {
    const {name, url, avatarUrl} = resolveAuthor(slug);
    const inner = <>
                    {avatarUrl && <img src={avatarUrl} alt={name} className="post-meta-avatar" />}
                    <span className="post-meta-author-name">{name}</span>
                  </>;
    return url ? <a key={slug} href={url} target="_blank" rel="noopener noreferrer" className="post-meta-author">
                    {inner}
                  </a> : <span key={slug} className="post-meta-author">{inner}</span>;
  })}
            </div>}
          {authors.length > 0 && formattedDate && <span className="post-meta-separator" aria-hidden="true">·</span>}
          {formattedDate && <span className="post-meta-date">{formattedDate}</span>}
        </div>}
      {image && <img src={image} alt="" className="post-meta-image" aria-hidden="true" />}
    </div>;
};

<PostMeta data={{ author: ["chadwcarlson"], date: "2021-08-10" }} />

<Note>
  Pre-release announcement: We’re making the `--visible-build` flag available as an option for environments.
</Note>

[Environment variables](https://platform.sh/blog/we-need-to-talk-about-the-env/) are one of the primary ways to ensure
repeatable builds on Platform.sh. They make it possible to reuse a previous build on a new branch, connecting to the
current environment's services and other backend resources.

Today we announce that the `--visible-build` flag, previously only available at the project level, is now an option for
environments, letting you tie your environment-specific variables to the build itself.

## A new option for making environment variables available during build

Environment-level variables have always been restricted to runtime. If you wanted a variable at build time, you needed
to set a project-level variable with the CLI or commit it in your
[.platform.app.yaml](https://docs.platform.sh/overview/yaml/what-is-yaml.html) file. In both cases, visibility at build
time meant that it was a part of the build image, something that should be considered almost like code. The build image
is at its core environment-agnostic, and it can be reused and moved to new environments freely until you change the
build process in some way, which gives you a lot of confidence when merging.

But there are times where you want a variable specific to one environment, such as distinguishing whether a Node.js s
erver should run in `production` or `development`, available at build time. For this reason, we've enabled the
`--visible-build` flag for variable creation [at the environment level](https://docs.platform.sh/development/variables.html).
If we continue with the Node.js example, we can consider the following commands:

```bash {filename="Terminal"} theme={null}
$ platform variable:create -l environment -e main --prefix env: --name NODE_ENV --value production --visible-build true --inheritable false
$ platform variable:create -l environment -e staging --prefix env: --name NODE_ENV --value development --visible-build true --inheritable true
```

In the first command, we’ve set `NODE_ENV` to `production` for the default branch, which makes sense for our production
application. In the second command, however, the variable is set to `development` for the `staging` environment, and it
will be inherited into each development environment that branches from it. This can be useful for running a much larger
test suite than you would run in production on each development environment, for
[enabling incremental builds](https://platform.sh/blog/headless-but-this-time-live-decoupled-drupal-with-gatsby/) with your
[decoupled applications](https://platform.sh/blog/time-to-breakup-three-reasons-to-decouple-your-application/), or for
providing write access at runtime for a backend headless CMS like Strapi (where it's forbidden in production).

## What’s changed

Introducing the `--visible-build` flag to environment-level variables is just one part of this release. There is another
potentially breaking change that you should keep in mind going forward. In the past, if you wanted to trigger a rebuild
on your app, you could simply add a small change, even a white space change, to your `.platform.app.yaml` file.

With this release, this is no longer the case. The `.platform.app.yaml` file itself is not a part of the build slug
reused across environments, nor is it available at all during builds. Instead, it’s only a subset of the values included
in that file—those attributes relevant to builds rather than runtime—that are tied to the slug.

For example, changing the version of Node.js your app uses will cause a full rebuild, whereas modifying the `post_deploy`
hook will not. Runtime keys that will no longer trigger rebuilds (but still trigger redeploys) when updated include:

* everything under `resources`
* `size`
* `disk`
* everything under `access`
* everything under `relationships`
* everything under `firewall`
* `hooks.deploy` and `hooks.post_deploy`
* everything under `web` except `web.mounts`
* everything under `workers` except `workers.X.mounts`
* everything under `crons`

While the `.platform.app.yaml` file isn’t available at build time anymore, you can still retrieve that information from
the `PLATFORM_APPLICATION` environment variable. But it will only include those attributes included in the build slug,
and none of those listed above (that is, until deploy time).

(The `.platform.app.yaml` file not being available during build means that it is not part of the tree of the application,
which also influences how the `PLATFORM_TREE_ID` variable is generated. If you compute this value yourself somewhere—we
never documented it, so you know who you are—you will now need to exclude the `.platform.app.yaml`. This should
otherwise not be of concern for most people.)

You can read about these changes in more detail in our updated
[variables documentation](https://docs.platform.sh/development/variables.html#variables-available-during-builds-and-at-runtime).

## An example: Using build environment variables to trigger a rebuild through a source operation

Build environment variables can change a lot of things for your apps. These variables now can become a part of the build
image, the same as project variables. This option opens up some interesting possibilities for fleets by creating a kind
of `platform rebuild` command if set up right.

In a previous article, I described a few options for maintaining a
[content delivery fleet](https://platform.sh/blog/source-operations-sorcery-summoning-the-multiheaded-gatsby-fleet/) on Platform.sh. The
example I used was a Drupal content store, decoupled from any number of frontend Gatsby presentation apps, that would
consume and present content across afleet. Thee apps could customize how the content was presented—such as whether it
was displayed on a mobile, desktop, gaming, or any other device—and then get triggered from the backend
[regularly via cron or automatically using a custom Drupal module](https://www.youtube.com/watch?v=qe_kXyruPYc) to
rebuild themselves using new content.

Build environment variables provide another method for triggering a rebuild through a
[source operation](https://docs.platform.sh/configuration/app/source-operations.html). The Drupal store example used a
dummy commit to a file in the repository root using the current date:

```yaml {filname=".platform.app.yaml"} theme={null}
source:
  operations:
    update:
      command: |
        echo Last Content Update:  $(date) > counter.txt
        echo "Create dummy commit to force rebuild for updated content."
        git commit -am "Source Operation: Updated content from backend."
```

If instead we create a `FRONTEND_REBUILD_COUNTER` variable for our presentation app:

```bash {filename="Terminal"} theme={null}
$ platform variable:create -l environment -e main --prefix env: --name FRONTEND_REBUILD_COUNTER --value 1` --visible-build true --inheritable false
```

We can redefine the source operation to increment the environment variable instead:

```yaml {filname=".platform.app.yaml"} theme={null}
source:
  operations:
    update:
      command: |
        platform variable:update FRONTEND_REBUILD_COUNTER $((FRONTEND_REBUILD_COUNTER+1))
```

Build variables are a part of the build slug, so simply updating their value will trigger a rebuild of, in this case,
the frontend Gatsby app with the latest content.

No doubt you have many ideas for additional places where the `--visible-build` flag will be useful. Feel free to share
them with us on our [community site](https://community.platform.sh).
