Changing Static Files Per-Branch

Goal

We’re deploying a static site that will serve a different file depending on whether it’s prod or dev.

Assumptions

You will need:

Problems

We have a static site that consumes an outside API from the browser.
This API has different keys for prod and dev mode.
How can a static site serve different files per environment?

Steps

1. Add your key files to the repository

$ touch keys/dev.json
$ touch keys/prod.json

2. Add a writable path

Supposing your site is served from the web directory, we’ll add a writable path underneath it to host our symlink.
Add the mount in your .platform.app.yaml file:

mounts:
    'web/keys':
        source: local
        source_path: keys

3. Symlink the changed files at deploy time

Now that we have our key files in the repository and a writable path available, we can use our deploy hook to create a symlink to the appropriate file:

hooks:
    deploy: |
        set -e
        if [ "$PLATFORM_BRANCH" = "master" ] ; then
            ln -sfv ~/keys/prod.json web/keys/key.json
        else
            ln -sfv ~/keys/dev.json web/keys/key.json
        fi

Conclusion

Now we can serve different content to the browser per-environment without changing the static nature of our site.

1 Like

this is a perfect example. thanks, @royall.
Some doubts, what’s the meaning of this line - ln -sfv ~/keys/prod.json? what is sfv?
Just one question, is it only working for the JSON file, or .js file path also work inside hook? (Suppose, I have two different js files inside the web/keys)

1 Like

what’s the meaning of this line - ln -sfv ~/keys/prod.json ? what is sfv?

This means “create a symbolic link from keys/prod.json in my home directory”. The ~ placeholder stands for the $HOME directory, which is /app in this case.

I’m using 3 options for ln:

  1. s for “symbolic link” (pointing to another file) instead of a hardlink (using the same inode at 2 locations)
  2. f for “force” in order to overwrite the link if it already exists
  3. v for “verbose” so it always prints a message in the deploy log

You can use this approach for files of any type that need to change at deploy time, as many as you need. You could even link a whole directory, if necessary.

1 Like

Thanks, @royall. Understand now.
Just one small doubt, correct me if I’m wrong.
the first one is the symlink u create temporarily in home dir and 2nd one is the actual file path. So, for symlink, '/web' not needed? I thought ‘home’ means where '.platform, web, .yaml' files are there.

This line:

ln -sfv ~/keys/prod.json web/keys/key.json

is a single command that creates a link at ~/web/keys/key.json pointing to the file ~/keys/prod.json.

Specifying the link’s target file with ~ in front creates an absolute path. If I used keys/prod.json instead, the link at /app/web/keys/key.json would use a relative path to /app/web/keys/keys/prod.json, which is not what we want.

More detail on symlinks at The Linux Documentation Project section 3.3.5

Thanks for this guide.

The problem that will very likely occur is for static sites that require outside API at bulld time (Static Site Generators). This is a current annoying limitation that would be great to overcome in Platform.sh’s roadmap, since the JAMStack is more and more important these days.

If someone finds a solution or workaround, I’m interested!

1 Like