Usability - Productivity - Business - The web - Singapore & Twins

Deploying your static app to your backend repo using GitHub Actions

Our solution has two parts: a backend written in JavaScript, providing the API and a front-end created in Angular, Ionic, React or whatever is the flavor of the day. Usually you would deploy a web server to handle the URL, host the static files and have it redirect the /api URL to our backend.

However there might be reasons (or that) that we can't or don't want to access the web server and need to serve your front-end app from the /static directory of our backend.

Planning and a little YAML

Merging the two repositories seems initially an easy option, it just would break our workflows, so a different solution needs to be devised. The ask is simple:

Merging UI files into the back-end

Whenever a change happens in the main branch of the front-end application (mostly through an approved pull request), the application should be build and the result transfered to the back-end application where a pull request merges it into main. Duplicate approvals shall be avoided. So we need:

  1. Automatic build on push to main
  2. Pull / Push the bundle changes from front-end to the back-end
  3. Create a pull request and merge it in back-end

GitHub Actions

Our solution's repositories are hosted on GitHub, so I thought, GitHub Actions could be a simple solution. Starting is quite easy. We create a .github/workflows directory in our repo and populate it with yaml files.

To give us a head start, the GitHub Marketplace lists over 5000 actions, that we can utilize. This makes typical tasks quite easy, once we find the right tool.

Since we will be working cross repository, we need a Personal Access Token (PAT). As a good practise we limit the token's permission to repo access only. Alternatively we could use a Deploy Key.

Our first workflow does nothing spectacular, short of the last step:

name: Reconcile front and backend

    branches: [main]

    name: Building UI
    runs-on: ubuntu-latest
      - name: Checkout UI
        uses: actions/checkout@v2
      - name: Deploy NodeJS
        uses: actions/setup-node@v1
          node-version: "12.x"
      - run: npm install
      - run: npm run build --if present
      - run: npm test
      - name: Git schenigans
        shell: bash
          GITHUB_TOKEN: ${{secrets.UI_PUSH_TOKEN }}
          REPO2: acme/back-end
          GITHUB_USER: john-doe
        run: |

GitHub will run step by step and terminate if one of the steps fail. Our last step is a shell script. I found it easier to get what I need there, than trying the various market place options. In a nutshell:

  • register the backend as sub-module. Since the front-end repo never goes back, no harm is done
  • copy the files
  • commit and push
# Send UI back to a new branch in backend
now=$(date +"%Y-%m-%d_%H-%M")
message="[UI Commit] ${now}"
# Step1 clone backend
git submodule add https://${GITHUB_USER}:${GITHUB_TOKEN}@github.com/$REPO2 backend
# Step3 update UI 
rm -rf backend/static/ui
mkdir -p backend/static/ui
cp build/* backend/static/ui/
cd backend
git config user.email "automation@acme.com"
git config user.name "Acme automation"
git add --all
git commit -m "$message"
git checkout -b ui/ui-$now
git push -u origin ui/ui-$now

The changes now appear in the back-end repository in a new branch carrying a time stamp it its name. Next stop are pull request and auto-merge. For the pull request we use autopull-ui.yml in the back-end repository:

name: Auto pull request on UI branches

    branches: ui/*
    name: Create pull request
    runs-on: ubuntu-latest
      - name: Checkout repo
        uses: actions/checkout@v2
      - name: Make pullR
        uses: repo-sync/pull-request@v2.3
          destination_branch: "main" 
          pr_label: "ui,automerge"
          github_token: ${{secrets.UI_PUSH_TOKEN }}

The key values here are the labels ui and automerge which set the stage for auto-merge-ui.yml that takes the pull request and merges it in. When approvers for the two repositories are different, we would skip that step:

name: automerge ui
      - labeled
      - unlabeled
      - synchronize
      - opened
      - edited
      - ready_for_review
      - reopened
      - unlocked
      - submitted
      - completed
  status: {}
    runs-on: ubuntu-latest
      - name: automerge
        uses: "pascalgn/automerge-action@v0.11.0"
          GITHUB_TOKEN: ${{secrets.UI_PUSH_TOKEN }}
          MERGE_DELETE_BRANCH: true
          MERGE_LABELS: automerge,ui

ANd there you have it: two repositories, one approval for changes. Make sure you check carefull when trying yourself

As usual YMMV!

Posted by on 04 October 2020 | Comments (0) | categories: GitHub NodeJS NodeRED


  1. No comments yet, be the first to comment