Search code examples
gitlabgitlab-pages

Is it possible to create gitlab-pages per branch


I have a vanilla JavaScript application that I host on GitLab Pages. Recently, I have been making changes and bug fixes that have been breaking the site, and I haven't noticed until already having pushed the changes.

In an effort to reduce user exposure to bugs, I would like to publish two sites in separate folders:

  • public/ : master branch; the official website
  • public/staging/ : staging branch; the nightly build

I would like for these to correspond to two different branches: master and staging

Reading GitLab CI for GitLab Pages, it sounds like this is not even possible. I'm hoping I'm reading this wrong.

default:
  image: node:latest

test:
  stage: test
  script:
  - npm install
  - node test.js
  only:
  - staging
  - master

staging:
  stage: deploy
  environment: staging
  script:
  - mkdir -p public/staging
  - cp -r www public/staging
  artifacts:
    paths:
    - public
  only:
  - staging

pages:
  stage: deploy
  environment: production
  script:
  - mkdir -p public
  - cp -r www public
  artifacts:
    paths:
    - public
  only:
  - master

Is this possible? Is it possible to deploy two different folders from two different branches?


Solution

  • Interestingly, it is possible to post from any branch, just not from any job.

    To do this, I needed to make two changes:

    1. I need to know the current state of the published data
    2. I need to change directory based on the current branch

    GitLab has the ability to cache folders. Generally this is used to speed up builds by caching downloaded drivers. There is no reasons I could not use this to store the public folder. This way when I make changes to staging, I will remember the state of the root application:

    cache:
      paths:
      - public
    

    The next trick would be to publish pages to the appropriate folder, depending on current branch being built. To do this, we can look to GitLab CI/CD Environment Variables; in particular:

    • CI_COMMIT_REF_SLUG: The current branch
    • CI_DEFAULT_BRANCH: the default branch (master)

    Knowing these two values, we can do a bit of bash to determine the correct place to write the content to.

    pages:
      stage: deploy
      script:
      - dir="$CI_COMMIT_REF_SLUG"
      - if [ "$CI_COMMIT_REF_SLUG" == "$CI_DEFAULT_BRANCH" ]; then dir=""; fi;
      - dir="public/$dir"
      - echo "Deploying to $dir"
      - mkdir -p $dir
      - cp -r www $dir
      artifacts:
        paths:
        - public
      only:
      - staging
      - master
    

    Don't forget to limit pages to only staging and master.

    WARNING

    I'm not satisfied with this.

    I think it would be better to maintain the cache somewhere completely different and copy them in at a later stage, but completely re-writing the public folder each time.

    The current solution will build cruft over time, but the basic idea is sound.