Coder Social home page Coder Social logo

prescottprue / firebase-ci Goto Github PK

View Code? Open in Web Editor NEW
72.0 6.0 10.0 1.22 MB

Simplified Firebase interaction for continuous integration

License: MIT License

JavaScript 99.84% Shell 0.16%
firebase continuous-integration travis-ci deployment environments

firebase-ci's Introduction

firebase-ci

Simplified Firebase interaction for continuous integration

NPM version Build Status Code Coverage License

Code Style

Features

  • Deploy to different Firebase projects based on Git Branch
  • Automatically use commit message as deploy message
  • Expose CI environment variables based on branch name
  • Mapping of CI environment variables to Firebase Functions Config
  • Optional Deploying of targets Functions, Hosting, Database (rules) and Storage (rules)
  • Skip For Pull Requests

Getting Started

  1. Generate a CI token through firebase-tools by running firebase login:ci

  2. Place this token within your CI environment under the variable FIREBASE_TOKEN

  3. Install firebase-ci into your project (so it is available on your CI): npm install --save-dev firebase-ci firebase-tools. If you don't want firebase-tools as a dev dependency, it can be left out as it is installed automatically if it doesn't exist.

  4. Set different Firebase project names in projects parameter of .firebaserc. The project aliases should match branch names like so:

    {
      "projects": {
        "prod": "prod-firebase",
        "master": "dev-firebase",
        "default": "dev-firebase"
      }
    }
  5. Add calls to the scripts within to your CI stages, here are a few example snippets:

    Github Actions (.github/workflows/*.yml)

    jobs:
      deploy:
        name: ${{ matrix.app }} Deploy
        runs-on: ubuntu-18.04
        steps:
          - name: Checkout Code
            uses: actions/checkout@v2
          
          ## Place other steps for installing deps, building, etc. here
          ## See the github-actions example for a full workflow
    
          # Deploy to Firebase project matching branch name in projects parameter of .firebaserc
          - name: Deploy To Firebase
            run: |
              $(npm bin)/firebase-ci deploy

    Travis (travis.yml)

    script:
      # Deploy to Firebase project matching branch name in projects parameter of .firebaserc
      - $(npm bin)/firebase-ci deploy

    NOTES:

    • firebase-ci can be used through the nodejs bin OR installed globally (npm bin is used here since instructions include adding firebase-ci as a dev dependency)
    • firebase-tools will be installed (from @latest) if it is not already installed locally or globally

Setting Project

There are a number of ways to set which Firebase project within .firebaserc is being used when running actions. Below is the order of for how the project is determined (default at bottom):

  • FIREBASE_CI_PROJECT environment variable (overrides all)
  • branch name (dependent on CI provider):
    • Github Actions - GITHUB_HEAD_REF or GITHUB_REF (refs/heads/ prefix is removed)
    • Travis-CI - TRAVIS_BRANCH
    • Gitlab - CI_COMMIT_REF_SLUG
    • Circle-CI - CIRCLE_BRANCH
    • wercker - WERCKER_GIT_BRANCH
    • drone-ci - DRONE_BRANCH
    • codeship - CI_BRANCH
    • bitbucket - BITBUCKET_BRANCH
  • fallback name (dependent on CI provider)
    • Gitlab - CI_ENVIRONMENT_SLUG
  • master
  • default (must be set within .firebaserc)

Examples are the same basic html file upload to Firebase hosting of different projects (or "environments") for different CI providers:

Why?

Advanced configuration of Firebase deployment is often necessary when deploying through continuous integration environment. Instead of having to write and invoke your own scripts, firebase-ci provides an easy way to create/modify advanced configurations.

FAQ

  1. What about Travis's firebase deploy option?

    Using the built in travis firebase deploy tool is actually a perfect solution if you want to do general deployment. You can even include the following to install stuff functions dependencies on Travis:

    after_success:
      - npm install --prefix ./functions
    
    deploy:
      provider: firebase
      project: $TRAVIS_BRANCH
      skip_cleanup: true
      token:
        secure: $FIREBASE_TOKEN

    This lets you deploy to whatever instance you want based on your branch (and config in .firebaserc).

    firebase-ci is for more advanced implementations including only deploying functions, hosting

Commands

  • copyVersion - Copy version from package.json to functions/package.json
  • createConfig - Create a config file based on CI environment variables (defaults to src/config.js)
  • deploy - Deploy to Firebase project matching branch name in .firebaserc (runs other firebase-ci actions by default unless -s is passed)
  • serve - Serve a the Firebase project matching branch name in .firebaserc using firebase serve
  • mapEnv - Map environment variables from CI Environment to Firebase functions environment
  • project - Output project name associated with CI environment (useful for commands that should be run for each environment)

copyVersion

It can be convenient for the version within the functions/package.json file to match the top level package.json. Enabling the copyVersion option, automatically copies the version number when calling deploy if the following config is provided:

"ci": {
  "copyVersion": true
}

setEnv

Expose environment variables to CI based on current branch.

With a .firebaserc that looks like so:

"ci": {
  "setEnv": {
    "master": {
      "SOME_VAR": "some value"
      "REACT_APP_ENV_VARIABLE": "val passed to react app"
    },
    "prod": {
      "SOME_VAR": "some other value"
      "REACT_APP_ENV_VARIABLE": "val passed to react app"
    }
  }
}

SOME_VAR and REACT_APP_ENV_VARIABLE will be exposed to environment variables of your CI based on branch. Meaning that on the master branch SOME_VAR will be set to "some value"

createConfig

DEPRECATED

Create a config file based on CI environment variables (defaults to src/config.js). Allows for creating files of different types based on the extension passed.

With the following environment variables: GA_TRACKINGID - Your google analytics tracking id INT_FIREBASE_WEBAPIKEY - API key of your integration/main Firebase instance (this can also be hard coded if you prefer since it doesn't) PROD_FIREBASE_WEBAPIKEY - API key of your production Firebase instance

And a .firebaserc that looks like so:

"ci": {
  "createConfig": {
    "master": {
      "version": "${npm_package_version}",
      "gaTrackingId": "${GA_TRACKINGID}",
      "firebase": {
        "apiKey": "${INT_FIREBASE_WEBAPIKEY}",
        "authDomain": "firebase-ci-int.firebaseapp.com",
        "databaseURL": "https://firebase-ci-int.firebaseio.com",
        "projectId": "firebase-ci-int",
        "storageBucket": "firebase-ci-int.appspot.com"
      }
    },
    "prod": {
      "version": "${npm_package_version}",
      "gaTrackingId": "${GA_TRACKINGID}",
      "firebase": {
        "apiKey": "${PROD_FIREBASE_WEBAPIKEY}",
        "authDomain": "firebase-ci.firebaseapp.com",
        "databaseURL": "https://firebase-ci.firebaseio.com",
        "projectId": "firebase-ci",
        "storageBucket": "firebase-ci.appspot.com"
      }
    }
  }
}

building on master branch, produces a file in src/config.js that looks like so:

export const version = "0.0.1" // or whatever version your package is
export const gaTrackingId = "123GA" // your google analytics tracking ID

export const firebase = {
  apiKey: "<- your app API key ->",
  authDomain: "<- your app name ->.firebaseapp.com",
  databaseURL: "https://<- your app name ->.firebaseio.com",
  projectId: "<- your app name ->",
  storageBucket: "<- your app name ->.appspot.com"
}

export default { version, gaTrackingId, firebase }

Options

Options can be passed as flags or within an options object if calling action as a function

--project - Project within .firebaserc to use when creating config file. Defaults to "default" then to "master" --path - Path to save the config file. Defaults to src/config.js

deploy

firebase-ci deploy

Options:

Deploy to Firebase. Following the API of firebase-tools, specific targets (i.e. functions, hosting) can be specified for deployment.

Default

  • Everything skipped on Pull Requests
  • Deployment goes to default project
  • If you have a functions folder, npm install will be run for you within your functions folder
  • copyVersion is called before deployment based on settings in .firebaserc, if you don't want this to happen, use simple mode.
  • mapEnv is called before deployment based on settings in .firebaserc, if you don't want this to happen, use simple mode.

Simple Mode

Option: --simple Flag: -s

Skip all firebase-ci actions and only run Firebase deployment

Info Option

Option : --info Flag: -i

Provide extra information from internal actions (including npm install of firebase-tools).

Only Option

Option : --only Flag: -o

Firebase targets to include (passed directly to firebase-tools)

Except Option

Option : --except

Deploy to all targets except specified (e.g. "database")

Force Option

Option : --force Flag: -f

Delete Cloud Functions missing from the current working directory without confirmation

Skipping Deploying Functions

If you have a functions folder, your functions will automatically deploy as part of using firebase-ci. For skipping this functionality, you may use the only flag, similar to the API of firebase-tools.

script:
  - $(npm bin)/firebase-ci deploy --only hosting

serve

firebase-ci serve

Options:

Serve using to firebase serve. Following the API of firebase-tools, specific targets (i.e. functions, hosting) can be specified for serving.

Default

  • Project alias matching branch name is served
  • If there is no matching alias, default project is used

Only Option

Option : --only Flag: -o

Firebase targets to include (passed directly to firebase-tools)

mapEnv

firebase-ci mapEnv

Set Firebase Functions variables based on CI variables. Does not require writing any secure variables within config files.

NOTE: Called automatically during firebase-ci deploy

Set the mapEnv parameter with an object containing the variables you would like to map in the following pattern:

TRAVIS_VAR: "firebase.var"
Example

CI variable is SOME_TOKEN="asdf" and you would like to set it to some.token on Firebase Functions you would provide the following config:

"ci": {
  "mapEnv": {
    "SOME_TOKEN": "some.token"
  }
}

Internally calls firebase functions:config:set some.token="asdf". This will happen for every variable you provide within mapEnv.

skipDependenciesInstall

Skip installing of dependencies including firebase-tools and node_modules within functions folder

skipToolsInstall

Skip installing of firebase-tools (installed by default when calling firebase-ci deploy without simple mode)

skipFunctionsInstall

Skip running npm install within functions folder (npm install is called within functions folder by default when calling firebase-ci deploy).

project

Get name of project associated with the CI environment

Example
echo "Project to deploy to $(firebase-ci project)"

projectID

Get the projectId associated with the CI environment. Initially loaded from ci.createConfig.${branchName}.firebase.projectId and falls back to project from project command

Example
echo "Project ID from config $(firebase-ci projectId)"

branch

Get the branch associated with the CI environment (loaded from environment variables)

Example
echo "Branch name from ci env $(firebase-ci branch)"

Roadmap

  • setCORS option for copying CORS config file to Cloud Storage Bucket
  • only setting non existent env vars with mapEnv
  • Support for Continuous Integration Tools other than Travis-CI

firebase-ci's People

Contributors

dependabot[bot] avatar dustingraves avatar kde713 avatar prescottprue avatar punkch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

firebase-ci's Issues

Error installing firebase-tools

Do you want to request a feature or report a bug?

Bug.

What is the current behavior?
I was trying to deploy this project, running firebase-ci deploy -s on travis produced the following error: Error installing firebase-tools.

What is the expected behavior?

Should deploy the build on firebase

firebase hosting:channel:deploy

Is firebase-ci hosting:channel:deploy supported? When trying to run this in Drone or locally, it just exits with no output.

Build Failure Still Passes

Do you want to request a feature or report a bug?

  • bug

What is the current behavior?
Failure in building/deployment causes tests to still pass

What is the expected behavior?
Failure within any part of the process should cause the build to be failed

Bug running gitlab job: undefinedno-use-before-declare is deprecated

Hello,

I'm getting an error when I try to run a build using Gitlab:

Error: functions predeploy error: Command terminated with non-zero exit code2
✖ Error: Error in firebase-ci:

 undefinedno-use-before-declare is deprecated. Since TypeScript 2.9. Please use the built-in compiler checks instead.
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! functions@ build: `tsc`
npm ERR! Exit status 2
npm ERR! 
npm ERR! Failed at the functions@ build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

My gitlab-ci.yml :

stages:
  - build
  - deploy_staging
  - build_production
  - deploy_production

variables:
  npm_config_cache: '$CI_PROJECT_DIR/.npm'
  CYPRESS_CACHE_FOLDER: '$CI_PROJECT_DIR/cache/Cypress'

cache:
  untracked: true
  key: ${CI_COMMIT_REF_SLUG}
  policy: pull # only pull cache, skip uploading
  paths:
    - .npm

## Install dependencies for React App and Cloud Functions.
## Script run before all stages unless otherwise overriden
before_script:
  - npm ci
  - npm ci --prefix functions

# Build Stage
## Installs dependencies, builds app, and saves results for later (artifacts).
Build:
  stage: build
  image: node:8
  when: always
  variables:
    FIREBASE_CI_PROJECT: 'stage' # deploy using stage project in .firebaserc
  except:
    variables:
      - $CI_COMMIT_MESSAGE =~ /skip-build/
  cache:
    untracked: true # track files that are untracked in git
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - .npm
  script:
    - npm run clean # remove existing build folder
    - npm run build:config # create env specific src/config.js
    - npm run build
    - npm run encrypt-dev

# Deploy Staging Stage
## Deploy React App and Firebase Functions
Deploy Staging:
  stage: deploy_staging
  image: node:8
  environment:
    name: staging
    url: ""
  when: on_success
  only:
    - master
  variables:
    FIREBASE_CI_PROJECT: 'stage' # deploy using stage project in .firebaserc
  artifacts:
    name: '$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG'
    expire_in: 1 weeks
    when: on_failure
    paths:
      - firebase-debug.log
  except:
    variables:
      - $CI_COMMIT_MESSAGE =~ /skip-deploy/
      - $CI_COMMIT_MESSAGE =~ /skip-prod-deploy/
  dependencies:
    - Build
  script:
    - npm run deploy

# Build Production Stage
## Build production version of bundle (has different config)
Build Production:
  stage: build_production
  image: node:8
  when: on_success
  only:
    - master
  artifacts:
    name: '$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG'
    expire_in: 1 week
    when: always
    paths:
      - build
  except:
    variables:
      - $CI_COMMIT_MESSAGE =~ /skip-deploy/
      - $CI_COMMIT_MESSAGE =~ /skip-prod-deploy/
  variables:
    FIREBASE_CI_PROJECT: 'prod' # deploy using prod project in .firebaserc
  script:
    - npm run clean # remove existing build folder
    - npm run build:config
    - npm run build # rebuild bundle with new config
    # Note: Functions are not rebuilt since a bundle with env specific config
    # is not created as with React App

# Deploy Production Stage
## Deploy React App and Cloud Functions to production environment
Deploy Production:
  stage: deploy_production
  image: node:8
  environment:
    name: production
    url: ""
  when: manual # Only allow run through button on Gitlab site
  only:
    - master
  variables:
    FIREBASE_CI_PROJECT: 'prod' # deploy using prod project in .firebaserc
  except:
    variables:
      - $CI_COMMIT_MESSAGE =~ /skip-deploy/
      - $CI_COMMIT_MESSAGE =~ /skip-prod-deploy/
  artifacts:
    name: '$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG'
    expire_in: 1 week
    when: on_failure
    paths:
      - firebase-debug.log
  script:
    - npm run deploy

The issue happens at Deploy Stage step

Bug: Running on GitabCI requires super user permission

I tried to use firebase-ci with gitlab-ci and when I tried to deploy I've got this exception:

ℹ Checking to see if firebase-tools is installed...
✖ Error: Error attempting to check for firebase-tools version.

 undefinedfs.js:646
  return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
                 ^

Error: EACCES: permission denied, open '/root/.npm/_npx/88/lib/node_modules/firebase/node_modules/grpc/package.json'
    at Object.fs.openSync (fs.js:646:18)
    at Object.fs.readFileSync (fs.js:551:33)
    at Run.parseOpts [as parseArgv] (/builds/aviyam1811/accountapp-web-application/node_modules/grpc/node_modules/node-pre-gyp/lib/node-pre-gyp.js:136:36)
    at Object.<anonymous> (/builds/aviyam1811/accountapp-web-application/node_modules/grpc/node_modules/node-pre-gyp/bin/node-pre-gyp:24:6)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

The user that run's the command can't reach the file for checking if firebase-tools existing because insufficient permissions.

bug(deploy): issue checking for firebase-tools version when not installed

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
image

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar.

What is the expected behavior?
It should still exit with 1, but the error message should be more clear (i.e. "firebase-tools version not found")

Which versions of dependencies, and which browser and OS are affected by this issue? Did this work in previous versions or setups?

mapEnv command fails with "TypeError: Cannot read property 'split' of undefined"

Do you want to request a feature or report a bug?

bug

What is the current behavior?

Running mapEnv locally using the node_module bin fails with a type error.

This seems to be because runCommand expects an object, but mapEnv passes it a string.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar.

Example .firebaserc file:

{
  "projects": {
    "default": "my-project",
    "master": "my-project"
  },
  "ci": {
    "mapEnv": {
      "SOME_VAR": "some.var"
    }
  }
}

Call to mapEnv:

./node_modules/firebase-ci/bin/firebase-ci mapEnv
ℹ Mapping Environment to Firebase Functions...
✖ Error: Error setting Firebase functions config variables from variables CI environment (mapEnv):

 TypeError: Cannot read property 'split' of undefined
    at Promise (/Users/elson/Projects/trello-sync/node_modules/firebase-ci/lib/utils/commands.js:41:80)
    at new Promise (<anonymous>)
    at runCommand (/Users/elson/Projects/trello-sync/node_modules/firebase-ci/lib/utils/commands.js:40:10)
    at /Users/elson/Projects/trello-sync/node_modules/firebase-ci/lib/actions/mapEnv.js:95:64
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (/Users/elson/Projects/trello-sync/node_modules/firebase-ci/lib/actions/mapEnv.js:36:103)
    at _next (/Users/elson/Projects/trello-sync/node_modules/firebase-ci/lib/actions/mapEnv.js:38:194)
    at /Users/elson/Projects/trello-sync/node_modules/firebase-ci/lib/actions/mapEnv.js:38:364
    at new Promise (<anonymous>)
    at /Users/elson/Projects/trello-sync/node_modules/firebase-ci/lib/actions/mapEnv.js:38:97

What is the expected behavior?

Firebase functions variables should be set as expected with no error thrown.

Which versions of dependencies, and which browser and OS are affected by this issue? Did this work in previous versions or setups?

firebase-ci: 0.6.0
Node: 11.14.0
OSX: 10.14.5

Workarounds

I have managed to make this run as expected by editing line 92 of mapEnv.js, so a suitable object is passed to runCommand:

const setConfigCommand = {
  command: createConfigSetString(mapEnvSettings)
};

However, on doing this I noted a separate issue with the resulting firebase function variable strings containing escaped " characters, e.g.:

firebase functions:config:get
{
    "some": {
        "var": "\"my value\""
    }
}

Passing the shell: true option to spawn in commands.js fixes this issue:

const child = spawn((0, _isArray2.default)(command) ? command[0] : command.split(' ')[0], args || (0, _compact2.default)((0, _drop2.default)(command.split(' '))), {
      env: process.env,
      shell: true
    });

bug(deploy): deploy can sometimes if commit message contains certain invalid characters

Do you want to request a feature or report a bug?
bug

What is the current behavior?
When commit message contains certain invalid characters such as emojis and multiple `.

What is the expected behavior?
Commit message should not break Firebase deployment regardless of its format or characters. If it does need to break build (i.e. message can not be inferred), the error message should be clear.

Which versions of dependencies, and which browser and OS are affected by this issue? Did this work in previous versions or setups?

No

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.