Deployment failing in github actions, unable to pass env to deploy command

Github Action to deploy a NextJS app with Sentry is failing with the following error

#16 8.299 Sentry CLI Plugin: Command failed: /build/node_modules/@sentry/cli/sentry-cli releases new xxxxxxxxxxxxxxxxxx
#16 8.299 error: API request failed
#16 8.299   caused by: sentry reported an error: Authentication credentials were not provided. (http status: 401)

So far going through Sentry docs shows that I have to set SENTRY_AUTH_TOKEN as the environment variable which I have done in github Repo > settings > secrets > actions. This is being accessed by the workflow file as shown below

./.github/workflow/something.yml

name: Deploy Staging

on:
  pull_request:
    branches:
      - "main"
      - "develop"

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

env:
  FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
  SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}


jobs:
  deploy:
    name: Deploying to fly

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: flyctl wrapper
        uses: superfly/flyctl-actions/setup-flyctl@master
        with:
          version: 0.0.355

      - name: flyctl deploy
        run: flyctl deploy --config ./fly.staging.toml --env SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN --remote-only

I’ve tried alternate versions of the deploy command like

flyctl deploy --config ./fly.staging.toml --build-arg SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN --remote-only
AND
flyctl deploy --config ./fly.staging.toml --build-secret SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN --remote-only

The error is definitely happening because sentry-cli is not able to pick up on the auth token, I’ve tested this on local (by using a config file)

Could someone help me out on how to pass the env to the build?

Hi! I think you might want to add a step and pass it to fly secrets set instead, like in this example:

If not, hopefully someone else around here also uses Github for their CI and can weigh in :pray:

Build secrets (flyctl deploy --build-secret...) need to be handled in your Dockerfile by mounting them and then reading the mounted secret - are you doing that in your Dockerfile?

For example, in your Dockerfile, use this to get the value from the --build-secret value passed in:

RUN --mount=type=secret,id=SENTRY_AUTH_TOKEN \
    echo "$(cat /run/secrets/SENTRY_AUTH_TOKEN)" \
    && echo "do more stuff"

:warning: You won’t want to “echo” the auth token file (which contains the secret value), but I did that just so you can see how its retrievable.

1 Like

Hey @fideloper-fly
Thanks for that! I was able to get this working when running a flyctl deploy command from my local shell after I made changes to run the mount secret command in the Dockerfile
However, Github actions are still failing with the same error.
I’ve rechecked that the secret is properly named in the settings and the value is correct but can’t get it to work :slightly_frowning_face:

Wonder where I might be going wrong.

Output of the action →

#16 [builder 5/7] RUN --mount=type=secret,id=SENTRY_AUTH_TOKEN
#16 CACHED
#17 [builder 6/7] RUN yarn run build:auth
#.
#.
#.
#17 2.975 info  - Linting and checking validity of types...
#17 5.076 info  - Creating an optimized production build...
#17 9.711 Failed to compile.
#17 9.711 
#17 9.711 Sentry CLI Plugin: Command failed: /build/node_modules/@sentry/cli/sentry-cli releases new OGwQJ39OxHIESq717rBC0
#17 9.711 error: API request failed
#17 9.711   caused by: sentry reported an error: Authentication credentials were not provided. (http status: 401)

I can’t fully tell the issue but I have a few guesses!

:one: First - be sure to use the --build-secret flag when deploying:

flyctl deploy --config ./fly.staging.toml \
    --build-secret SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN --remote-only

:two: Second - After mounting the secret in the Dockerfile, the value for that secret will live in file /run/secrets/SENTRY_AUTH_TOKEN, but it’s up to you to do something with that secret.

:point_right: It won’t become available as an env var to your Docker build automatically. (I suspect this is the point of confusion)

It looks like the step that fails is running the sentry release command: /build/node_modules/@sentry/cli/sentry-cli releases new xxxxxxxxxxxxxxxxxx ?

In that case, your Dockerfile may need some equivalent to this:

RUN SENTRY_AUTH_TOKEN="$(cat /run/secrets/SENTRY_AUTH_TOKEN)" /build/node_modules/@sentry/cli/sentry-cli releases new xxxxxxxxxxxxxxxxxx

… or something like that. The specifics of how that’s done will be up to how the Dockerfile is setup.

The main point is, you still need to get that auth token value and do something with it. There’s no magic there, from Docker’s point of view, the secret is just a string sitting in a text file.

Let me know if I can clarify anything specific there!

1 Like

An example of React app build with Dockerfile nginx and flyctl github actions

Dockerfile

FROM node:17-alpine as build

WORKDIR /app

ARG REACT_APP_SUPABASE_URL
ARG REACT_APP_SUPABASE_ANON_KEY
ARG REACT_APP_BACKEND_URL

ENV REACT_APP_SUPABASE_URL=$REACT_APP_SUPABASE_URL
ENV REACT_APP_SUPABASE_ANON_KEY=$REACT_APP_SUPABASE_ANON_KEY
ENV REACT_APP_BACKEND_URL=$REACT_APP_BACKEND_URL

ARG NODE_ENV=production
RUN echo ${NODE_ENV}

COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:1.19
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY --from=build /app/build /usr/share/nginx/html

The github actions

name: Fly Deploy
on: [push]

env:
  FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
  REACT_APP_SUPABASE_URL: ${{ secrets.REACT_APP_SUPABASE_URL }}
  REACT_APP_SUPABASE_ANON_KEY: ${{ secrets.REACT_APP_SUPABASE_ANON_KEY }}
  REACT_APP_BACKEND_URL: ${{ secrets.REACT_APP_BACKEND_URL }}

jobs:

  deploy:
    name: Deploy App
    runs-on: ubuntu-latest
    outputs:
      backend: ${{ steps.filter.outputs.backend }}
      frontend: ${{ steps.filter.outputs.frontend }}
    steps:
      - uses: actions/checkout@v3
      - uses: dorny/paths-filter@v2
        id: filter
        with:
          filters: |
            backend:
              - 'backend/**'
            frontend:
              - 'frontend/**'

  backend:
    needs: deploy
    if: ${{ needs.deploy.outputs.backend == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: superfly/flyctl-actions/setup-flyctl@master
      - run: flyctl deploy
        working-directory: ./backend
        
  frontend:
    needs: deploy
    if: ${{ needs.deploy.outputs.frontend == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: superfly/flyctl-actions/setup-flyctl@master
      - run: |
          flyctl deploy --remote-only \
          --build-arg REACT_APP_SUPABASE_URL=${{ secrets.REACT_APP_SUPABASE_URL }} \
          --build-arg REACT_APP_SUPABASE_ANON_KEY=${{ secrets.REACT_APP_SUPABASE_ANON_KEY }} \
          --build-arg REACT_APP_BACKEND_URL=${{ secrets.REACT_APP_BACKEND_URL }}
        working-directory: ./frontend

1 Like

The --build-arg is a good way to pass in build-time variables from GitHub actions context to the Docker file. You then need to assign those variables to the Docker build environment in the Dockerfile, and then it will be used by the npm run build command properly.

You can check out this blog post an example on how to do it in a production app.