Generating Badges from Badgeyay API

Badgeyay is a badge generator and its main functionality is generating badges. Since the beginning of GSoC 2018 period, Badgeyay is under refactoring and remodeling process. We have introduced many APIs to make sure that Badgeyay works. Now, the badge generator has an endpoint to generate badges for your events/meetups

How to create badges?

Creating badges using the newly formed API is simpler than before. All you need to do is pass some basic details of the image you want, the data you want, the size and the color of font etc to the API and woosh! Within a blink of your eye the badges are generated.

Backend requires some data fields to generate badges

{
"csv" : "a731h-jk12n-bbau2-saj2-nxg31.csv",
"image" : "p2ja7-gna398-c23ba-naj31a.png",
"text-color" : "#ffffff"
}

“csv” is the filename of the csv that the user uploads and get back as a result, “image” is the image name that user gets after a successful upload to the respective APIs, “text-color” is the color of the text that the user wants on the badges.

Output of the API

{
"output" :  "path-to-the-pdf-of-the-badge-generated",
.
.
}

What is happening behind the scene?

Once the user sends the data to the API, the required route is triggered and the data is checked,If the data is not present an error response is sent back to the user so as to inform them about the misplacement or improper format of data.

import os
from flask import Blueprint, jsonify, request
from flask import current_app as app
# from api.helpers.verifyToken import loginRequired
from api.utils.response import Response
from api.utils.svg_to_png import SVG2PNG
from api.utils.merge_badges import MergeBadges


router = Blueprint('generateBadges', __name__)


@router.route('/generate_badges', methods=['POST'])
def generateBadges():
try:
data = request.get_json()
except Exception as e:
return jsonify(
Response(401).exceptWithMessage(str(e),'Could not find any JSON'))

if not data.get('csv'):
return jsonify(
Response(401).generateMessage('No CSV filename found'))
if not data.get('image'):
return jsonify(Response(401).generateMessage('No Image filename found'))
csv_name = data.get('csv')
image_name = data.get('image')
text_color = data.get('text-color') or '#ffffff'
svg2png = SVG2PNG()
svg2png.do_text_fill('static/badges/8BadgesOnA3.svg', text_color)
merge_badges = MergeBadges(image_name, csv_name)
merge_badges.merge_pdfs()

output = os.path.join(app.config.get('BASE_DIR'), 'static', 'temporary', image_name)
return jsonify(
Response(200).generateMessage(str(output)))

 

After the data is received, we send it to MergeBadges which internally calls the GenerateBadges class which creates the badges.

Brief explanation of the Badge Generation Process:
- Gather data from the user- Fill the SVG for badges with the text color

- Load the image from uploads directory
- Generate badges for every individual
- Create PDFs for individual Badges
- Merge those PDFs to provide an all-badges pdf to the user

 

And this is how we generated badges for the user using the Badgeyay Backend API.

How is this effective?

We are making sure that the user chooses the image and csv that he/she has uploaded only,

In this way we maintain a proper workflow, we also manage these badges into the database and hence using the filenames helps a lot.It does not involve sending huge files and a lot of data like we had in the previous API.

Earlier, we used to send the image and the csv altogether that caused a serious mismanagement of the project. In this case we are accepting the CSVs and the Images on different API routes and then using the specific image and csv to make badges. We can now more easily relate to the files associated with each and every badge and henceforth we can easily manage them in the database.

Further Improvements

We will work on adding security to the route so that not anyone can create badges. We also need to integrate database into badges generated service so that we can maintain the badges that the user has generated.

Resources

Continue Reading Generating Badges from Badgeyay API

File and Image Upload API in Badgeyay

Badgeyay has seen many changes in the recent past during its refactoring. It started off with backend and we have now transition to remodeling backend as well.

The backend transition is working perfectly. We have established sufficient APIs so far to get it working.

Some of the most important APIs that we created are

  • Image Upload API
  • File Upload API

Why do we need APIs?

We need APIs so that the frontend written in Ember JS can coordinate with the backend written in Python Flask with the database being PostgreSQL.

Creating the APIs

Creating these APIs is easy and straightforward. The following APIs are written in Python Flask with a backend database support of PostgreSQL.

Image Upload API

The image upload API considers that the frontend is sending the Image as a base64 encoded string and the backend is supposed to accept this string and convert this string into an image and save it onto the server.

We proceed by creating a file named fileUploader.py and code the following API.

First of all, we need to declare the imports

from flask import Blueprint, request, jsonify
from api.utils.response import Response
from api.helpers.verifyToken import loginRequired
from api.helpers.uploads import saveToImage, saveToCSV

Now, let’s create a route for image upload.

router = Blueprint('fileUploader', __name__)

@router.route('/image', methods=['POST'])
@loginRequired
def uploadImage():
try:
image = request.json['data']
except Exception as e:
return jsonify(
Response(400).exceptWithMessage(
str(e),
'No Image is specified'))

extension = request.json['extension']
try:
imageName = saveToImage(imageFile=image, extension=extension)
except Exception as e:
return jsonify(
Response(400).exceptWithMessage(
str(e),
'Image could not be uploaded'))

return jsonify(
Response(200).generateMessage({
'message': 'Image Uploaded Successfully',
'unique_id': imageName}))

We are using the saveToImage function to actually save the image to the backend server.

The function definition of saveToImage function is given below.

def generateFileName():
return str(uuid.uuid4())def saveToImage(imageFile=None, extension='.png'):
imageName = generateFileName() + extension
imageDirectory = os.path.join(app.config.get('BASE_DIR'), 'static', 'uploads', 'image')if not os.path.isdir(imageDirectory):
os.makedirs(imageDirectory)imagePath = os.path.join(imageDirectory, imageName)
image = open(imagePath, "wb")
image.write(imageFile.decode('base64'))
image.close()

return imageName

Similarly, we are using file upload route to upload files to backend server.

The route for uploading files along with its helper function saveToCSV is given below.

def saveToCSV(csvFile=None, extension='.csv'):
csvName = generateFileName() + extension
csvDirectory = os.path.join(app.config.get('BASE_DIR'), 'static', 'uploads', 'csv')if not os.path.isdir(csvDirectory):
os.makedirs(csvDirectory)csvPath = os.path.join(csvDirectory, csvName)
csvFile.save(csvPath)return csvName
@router.route('/file', methods=['POST'])
@loginRequired
def fileUpload():
if 'file' not in request.files:
return jsonify(
Response(401).generateMessage(
'No file is specified'))file = request.files['file']
try:
csvName = saveToCSV(csvFile=file, extension='.csv')
except Exception as e:
return jsonify(
Response(400).exceptWithMessage(
str(e),
'CSV File could not be uploaded'))return jsonify(
Response(200).generateMessage({
'message': 'CSV Uploaded successfully',
'unique_id': csvName}))

What happens to the uploaded files?

The uploaded files gets saved into their respective directories, i.e. static/uploads/csv for CSV files and static/uploads/images for Image uploads.

The developer can view them from their respective folders. The static folder has been added to .gitignore  so that it does not gets uploaded to github repository.

Everything has been taken care of with immense accuracy and proper error handling.

Further Improvements

Further improvements in Badgeyay includes adding separate database models, work on adding a beautiful frontend and to add proper routes for completing the backend.

Resources

Continue Reading File and Image Upload API in Badgeyay

Implementing Sign up Feature through Email in Badgeyay

Badgeyay project is divided into two parts i.e front-end of Ember JS and back-end with REST-API programmed in Python.

We already have logging In features implemented with the help of Firebase Authentication. A User can login in the Badgeyay with the help of Google, Facebook and Twitter credentials through a single click. Now, the challenging part is to implement the sign up with Email feature in Frontend and Backend to enable the user to signup and Login with the help of Email and Password

In this blog, I will be discussing how I set up Sign up feature in Badgeyay frontend to send the data in backend besides having Oauth logging features in Badgeyay integrated with Firebase in my Pull Request.

The sign up form is already implemented and I have already mentioned in my previous blog. So we need to send the form data to backend to register user so that user can login using the registered credentials. We need an Adapter, Signup action, controller , Signup Data model  and a serializer for doing this task.

Let’s get started and understand the terminologies before implementing the feature.

What is Ember Data ?

It is a data management library for Ember Framework which help to deal with persistent application data.
We will generate Ember data model using Ember CLI in which we will define the data structure we will be requiring to provide to our application for User Signup.

Step 1 : Generate ember data model for signup.

$ ember g model user-signup

 

Step 2: Define the user-signup data model.

import DS from 'ember-data';

const { Model, attr } = DS;

export default Model.extend({
  username : attr('string'),
  email    : attr('string'),
  password : attr('string')
});

 

What are Actions ?

We already have the signup form implemented in frontend. Now we need to provide a action to the form when the user enters the data in form.

If we add the {{action}} helper to any HTML DOM element, when a user clicks the element, the named event will be sent to the template’s corresponding component or controller.

<button class="ui orange submit button" {{ action 'signUp' }}>Sign Up</button>

 

We need to add signUp action in sign-up component and controller.

// Signup Controller 
import Controller from '@ember/controller';

import { inject as service } from '@ember/service';

export default Controller.extend({
  routing : service('-routing'),
  actions : {
    signUp(email, username, password) {
      const _this = this;
      let user_ = this.get('store').createRecord('user-signup', {
        email,
        username,
        password
      });
      user_.save()
        .then(record => {
          _this.transitionToRoute('/');
        })
        .catch(err => {
          console.log(err);
        });
    }
  }
});

// Sign up Component
import Component from '@ember/component';

export default Component.extend({
  init() {
    this._super(...arguments);
  },

  email     : '',
  password  : '',
  isLoading : false,

  actions: {
    signUp(event) {
      event.preventDefault();
      let email = '';
      let password = '';
      let username = '';
      email = this.get('email');
      password = this.get('password');
      username = this.get('username');
      this.get('signUp')(email, username, password);
    }
  },
});

 

What is an Adapter ?

An adapter determines how the data is persisted to a backend data store. We can configure the backend host, URL format and headers for REST API.

Now as we have specific Data Model for User Signup that we will be using for communicating with its backend so we have to create User-Signup Adapter with the help of Ember-CLI.

Step 1: Generate User Signup Adapter by following together.

$ ember generate adapter user-signup

 

Step 2: Extend the Adapter according to User-Signup Model.

import DS from 'ember-data';
import ENV from '../config/environment';

const { APP } = ENV;
const { JSONAPIAdapter } = DS;

export default JSONAPIAdapter.extend({
  host        : APP.backLink,
  pathForType : () => {
    return 'user/register';
  }
});

 

What are Serializers ?

Serializers format the Data sent to and received from the backend store. By default, Ember Data serializes data using the JSON API format.

Now as we have specific Data Model for User Signup that we will be using for communicating with its backend so we have to create User-Signup Serializer with the help Ember-CLI.

Step 1: Generate the User Signup Adapter by following command:

$ ember generate serializer user-signup

 

Step 2: Extend the serializer according to User-Signup Model.

import DS from 'ember-data';

const { JSONAPISerializer } = DS;

export default JSONAPISerializer.extend({

  serialize(snapshot, options) {
    let json = this._super(...arguments);
    return json;
  },

  normalizeResponse(store, primaryModelClass, payload, id, requestType) {
    return payload;
  }
});

 

We have successfully set up the User Signup in the frontend and data is communicated to backend in JSON API v1 specification with the help of serializers and Adapters.

This is how I set up Sign up feature in Badgeyay frontend to send the data in backend besides having Oauth logging features in Badgeyay integrated with Firebase in my Pull Request.

Resources:

  1. Ember Docs – Link
  2. Firebase Docs – Link
  3. Badgeyay Repository – Link
Continue Reading Implementing Sign up Feature through Email in Badgeyay

Creating Forms and their validation using Semantic UI in Badgeyay

Badgeyay project is now divided into two parts i.e front-end of Ember JS and back-end with REST-API programmed in Python.

After a discussion, we have finalized to go with Semantic UI framework which uses simple, common language for parts of interface elements, and familiar patterns found in natural languages for describing elements. Semantic allows to build beautiful websites fast, with concise HTML, intuitive javascript and simplified debugging, helping make front-end development a delightful experience. Semantic is responsively designed allowing a web application to scale on multiple devices. Semantic is production ready and partnered with Ember framework which means we can integrate it with Ember frameworks to organize our UI layer alongside our application logic.

In this blog, I will be discussing how I added Log In and Signup Forms and their validations using Semantic UI for badgeyay frontend in my Pull Request.

Let’s get started and understand it step by step.

Step 1:

Generate ember components of Login and Sign up by using the following command :

$ ember generate component forms/login-form
$ ember generate component forms/signup-form

 

Step 2:

Generate Login and Sign up route by following commands.

$ ember generate route login
$ ember generate route signup 

 

Step 3:

Generate Login and Sign up controller by following commands.

$ ember generate controller login
$ ember generate controller signup

 

Step 4:

Now we have set up the components, routes, and controllers for adding the forms for login and Sign up. Now let’s start writing HTML in handlebars, adding validations and implementing validations for the form components. In this blog, I will be sharing the code of Login form and actions related to logging In of user. You can check the whole code my Pull Request which I have made for adding these Forms.

Step 4.1: Creating a Login Form

<div class="ui hidden divider"></div>
<div class="ui raised segment">
    <div class="ui stackable column doubling centered grid">
        <div class="ui middle aligned center aligned grid">
            <div class="row" >
                <div class="column">
                    <h1 class="ui orange header">
                        Welcome back !
                        <div class="sub header">We're happy  helping you get beautiful name badges.</div>
                    </h1>
                    <div class="ui hidden divider"></div>
                    <form class="ui form">
                        <div class="ui stacked element">
                            <div class="field required">
                                <div class="ui left icon input">
                                    <i class="mail icon"></i>
                                    {{input type="text" value=email name="email" placeholder="E-mail address"}}
                                </div>
                            </div>
                            <div class="field required">
                                <div class="ui left icon input">
                                    <i class="lock icon"></i>
                                    {{input type="password" value=password name="password" placeholder="Password"}}
                                </div>
                            </div>
                            <button class="ui button orange fluid" style="margin-bottom: 10px;" {{ action 'logIn' 'password' }}>Log In</button>
                            <a href="#" class="text muted"> Forgot your password ?</a>
                            <div class="ui divider"></div>
                            <a href="{{href-to 'signup'}}" class="text muted weight-800">Don't have an account yet? Signup</a>
                        </div>
                    </form>
                    <div class="ui horizontal divider">
                        Or
                    </div>
                    <h1 class="ui header">
                        <div class="sub header">Login with</div>
                    </h1>
                </div>
            </div>
            <div class="three column row">
                <div class="column">
                    <div class="ui vertical animated red button fluid" {{ action 'logIn' 'google' }}>
                        <div class="hidden content">Google</div>
                        <div class="visible content">
                            <i class="google plus icon"></i>
                        </div>
                    </div>
                </div>
                <div class="column">
                    <div class="ui vertical animated violet button fluid" tabindex="0" {{ action 'logIn' 'facebook' }}>
                        <div class="hidden content">Facebook</div>
                        <div class="visible content">
                            <i class="facebook f icon"></i>
                        </div>
                    </div>
                </div>
                <div class="column">
                    <div class="ui vertical animated blue button fluid" tabindex="0" {{ action 'logIn' 'twitter' }}>
                        <div class="hidden content">Twitter</div>
                        <div class="visible content">
                            <i class="twitter icon"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

 

Step 4.2: Adding Form Validations

import Component from '@ember/component';

export default Component.extend({
  init() {
    this._super(...arguments);
  },

  actions: {
    logIn(provider) {
      let email = '';
      let password = '';
      if (provider == 'password') {
        email = this.get('email');
        password = this.get('password');
      }
      this.get('login')(provider, email, password);
    },

    logOut() {
      this.get('session').close();
    }
  },

  didRender() {
    this.$('.ui.form')
      .form({
        inline : true,
        delay  : false,
        fields : {
          email: {
            identifier : 'email',
            rules      : [
              {
                type   : 'email',
                prompt : 'Please enter a valid email address'
              }
            ]
          },
          password: {
            identifier : 'password',
            rules      : [
              {
                type   : 'empty',
                prompt : 'Please enter a password'
              }
            ]
          }
        }
      })
    ;
  }
});

 

Step 4.3: Adding Login Actions

import Ember from 'ember';

import Controller from '@ember/controller';

const { inject } = Ember;

export default Controller.extend({
  session: inject.service(),
  beforeModel() {
    return this.get('session').fetch().catch(function() {});
  },
  actions: {
    login(provider, email, password) {
      const that = this;
      if (provider === 'password') {
        this.get('session').open('firebase', {
          provider: 'password',
          email,
          password
        }).then(function(userData) {
          console.log(userData);
          that.transitionToRoute('/');
        }).catch(function(err) {
          console.log(err.message);
        });
      } else {
        const that = this;
        this.get('session').open('firebase', {
          provider
        }).then(function(userData) {
          console.log(userData);
          that.transitionTo('/');
        }).catch(function(err) {
          console.log(err.message);
        });
      }
    },

    logOut() {
      this.get('session').close();
    }
  }
});

 

I have made Login form and in a similar way I implemented the SignUp form and complete code can be seen in my Pull Request.

Now, we are done with writing HTML in handlebars, adding validations and implementing validations for the form components.

Step 5:

Now run the server to see the implemented changes by the following command.

$ ember serve

 

It will show like this :

Navigate to localhost to see the changes.

  • Login Form

  • Sign up  Form

  • Form Validations

Now we are all done with setting up Log In and Signup Forms and their validations using Semantic UI in the badgeyay repository.

This is how I have added Log In and Signup Forms and their validations in my Pull Request.

Resources:

  • Semantic UI Docs – Link
  • Ember Docs – Link
Continue Reading Creating Forms and their validation using Semantic UI in Badgeyay

Implementing Database Migrations to Badgeyay

Badgeyay project is divided into two parts i.e front-end of Ember JS and back-end with REST-API programmed in Python.

We have integrated PostgreSQL as the object-relational database in Badgeyay and we are using SQLAlchemy SQL Toolkit and Object Relational Mapper tools for working with databases and Python. As we have Flask microframework for Python, so we are having Flask-SQLAlchemy as an extension for Flask that adds support for SQLAlchemy to work with the ORM.

One of the challenging jobs is to manage changes we make to the models and propagate these changes in the database. For this purpose, I have added Added Migrations to Flask SQLAlchemy for handling database changes using the Flask-Migrate extension.

In this blog, I will be discussing how I added Migrations to Flask SQLAlchemy for handling Database changes using the Flask-Migrate extension in my Pull Request.

First, Let’s understand Database Models, Migrations, and Flask Migrate extension. Then we will move onto adding migrations using Flask-Migrate. Let’s get started and understand it step by step.

What are Database Models?

A Database model defines the logical design and structure of a database which includes the relationships and constraints that determine how data can be stored and accessed. Presently, we are having a User and file Models in the project.

What are Migrations?

Database migration is a process, which usually includes assessment, database schema conversion. Migrations enable us to manipulate modifications we make to the models and propagate these adjustments in the database. For example, if later on, we make a change to a field in one of the models, all we will want to do is create and do a migration, and the database will replicate the change.

What is Flask Migrate?

Flask-Migrate is an extension that handles SQLAlchemy database migrations for Flask applications using Alembic. The database operations are made available through the Flask command-line interface or through the Flask-Script extension.

Now let’s add support for migration in Badgeyay.

Step 1 :

pip install flask-migrate

 

Step 2 :

We will need to edit run.py and it will look like this :

import os
from flask import Flask
from flask_migrate import Migrate  // Imported Flask Migrate

from api.db import db
from api.config import config

......

db.init_app(app)
migrate = Migrate(app, db) // It will allow us to run migrations
......

@app.before_first_request
def create_tables():
    db.create_all()

if __name__ == '__main__':
    app.run()

 

Step 3 :

Creation of Migration Directory.

 export FLASK_APP=run.py
 flask db init

 

This will create Migration Directory in the backend API folder.

└── migrations
    ├── README
    ├── alembic.ini
    ├── env.py
    ├── script.py.mako
    └── versions

 

Step 4 :

We will do our first Migration by the following command.

flask db migrate

 

Step 5 :

We will apply the migrations by the following command.

flask db upgrade

 

Now we are all done with setting up Migrations to Flask SQLAlchemy for handling database changes in the badgeyay repository. We can verify the Migration by checking the database tables in the Database.

This is how I have added Migrations to Flask SQLAlchemy for handling Database changes using the Flask-Migrate extension in my Pull Request.

Resources:

  • PostgreSQL Docs    – Link
  • Flask Migrate Docs  – Link
  • SQLAlchemy Docs  – Link
  • Flask SQLAlchemy Docs – Link
Continue Reading Implementing Database Migrations to Badgeyay

Refactoring and Remodeling Badgeyay API

When we build a full scale production application, we make sure that everything is modeled correctly and accordingly to the need of the code. The code must be properly maintained as well as designed in such a way that it is less prone to errors and bugs.

Badgeyay is also targeting to be a full production application, and in order to achieve it we first need to re-factor the code and model it using a strong yet maintainable structure.

What is the current state of Badgeyay?

Currently Badgeyay is divided into two sub folders.

\badgeyay
    \frontend
    \backend
    .
    .

It is backed by two folders, viz backend and frontend. The ‘backend’ folder handles the API that the service is currently running. The ‘frontend’ folder houses the Ember based frontend logic of the application.

Improvements to Badgeyay Backend

We have worked on improving Backend for Badgeyay. Instead of traditional methods, i.e. current method, of API development; We employ a far better approach of using Flask Blueprint as a method of refactoring the API.

The new backend API resides inside the following structure.

\badgeyay
    \backend
        \blueprint
            \api

The API folder currently holds the new API being formatted from scratch using

  • Flask Blueprint
  • Flask Utilities like jsonify, response etc

The new structure of Badgeyay Backend will follow the following structure

api
    \config
    \controllers
    \helpers
    \models
    \utils
    db.py
    run.py

The folders and their use cases are given below

  • \config
    • Contain all the configuration files
    • Configurations about URLs, PostgreSQL etc
  • \controllers
    • This will contain the controllers for our API
    • Controllers will be the house to our routes for APIs
  • \helpers
    • Helpers folder will contain the files directly related to API
  • \models
    • Models folder contains the Schemas for PostgreSQL
    • Classes like User etc will be stored in here
  • \utils
    • Utils will contain the helper functions or classes
    • This classes or functions are not directly connected to the APIs
  • db.py
    • Main python file for Flask SQLAlchemy
  • run.py
    • This is the main entry point.
    • Running this file will run the entire Flask Blueprint API

How does it help?

  • It helps in making the backend more solid.
  • It helps in easy understanding of application with maintained workflow.
  • Since we will be adding a variety of features during Google Summer of Code 2018 therefore we need to have a well structured API with well defined paths for every file being used inside it.
  • It will help in easy maintaining for any maintainer on this project.
  • Development of the API will be faster in this way, since everything is divided into sub parts therefore many people can work on many different possibilities on the same time.

Further Improvements

Since this structure has been setup correctly in Badgeyay now, so we can work on adding separate routes and different functionalities can be added simultaneously.

It ensures faster development of the project.

Resources

Continue Reading Refactoring and Remodeling Badgeyay API

Auto Deployment of Badgeyay Backend by Heroku Pipeline

Badgeyay project is now divided into two parts i.e front-end of Ember JS and back-end with REST-API programmed in Python. One of the challenging job is that, it should support the uncoupled architecture. Now, we have to integrate Heroku deployed API with Github which should auto deploy every Pull Request made to the Development Branch and help in easing the Pull Request review process.

In this blog, I’ll be discussing how I have configured Heroku Pipeline to auto deploy every Pull request made to the Development Branch and help in easing the Pull Request review process  in Badgeyay in my Pull Request.
First, Let’s understand Heroku Pipeline and its features. Then we will move onto configuring the Pipeline file to run auto deploy PR.. Let’s get started and understand it step by step.

What is Heroku Pipeline ?

A pipeline is a group of Heroku apps that share the same codebase. Each app in a pipeline represents one of the following steps in a continuous delivery workflow:

  • Review
  • Development
  • Staging
  • Production

A common Heroku continuous delivery workflow has the following steps:

  • A developer creates a pull request to make a change to the codebase.
  • Heroku automatically creates a review app for the pull request, allowing    developers to test the change.
  • When the change is ready, it’s merged into the codebase Default branch.
  • The Default branch is automatically deployed to staging for further testing.
  • When it’s ready, the staging app is promoted to production, where the change is available to end users of the app.

In badgeyay, I have used Review App and Development App steps for auto deployment of Pull Request.

Pre – requisites:

  • You should have admin rights of the Github Repository.
  • You should be the owner of the Heroku deployed app.
  • For creating a Review App , Below mentioned files are needed to be in the root of the project repository to trigger the Heroku Build.

1. App.json

{
    "name": "BadgeYay-API",
    "description": "A fully functional REST API for badges generator using flask",
    "repository": "https://github.com/fossasia/badgeyay/backend/",
    "keywords": [
        "badgeyay",
        "fossasia",
        "flask"
    ],
    "buildpacks": [
        {
            "url": "heroku/python"
        }
    ]
}
2. Procfile

web: gunicorn --pythonpath backend/app/ main:app

 

Now, I have fulfilled all the prerequisites needed for integrating Github repository to Heroku Deployed Badgeyay API. Let’s move to Heroku Dashboard of the Badgeyay API and implement auto deployment of every Pull Request.

Step 1 :

Open the heroku Deployed App on the dashboard. Yow will see following tabs in top of the dashboard.

Step 2 :

Click on Deploy and first create a new pipeline by giving a name to it and choose a stage for the pipeline.

Step 3 :

  • Choose a Deployment Method. For the badgeyay project, I have  integrated Github for auto deployment of PR.
  • Select the repository and connect with it.
  • You will receive a pop-up which will ensure that repository is connected to Heroku.

Step 4 :
Enable automatic deploys for the Github repository.

Step 5 :

Now after adding the pipeline, present app get nested under the pipeline. Click on the pipeline name on the top and now we have a pipeline dashboard like this :

Step 6:

Now for auto deployment of PR, enable Review Apps by filling the required information like this :

Step 7:

Verify by creating a test PR after following every above mentioned steps.

 

Now we are all done with setting up auto deployment of every pull request to badgeyay repository.

This is how I have configured Heroku Pipeline to auto deploy every Pull request made to the Development Branch and help in easing the Pull Request review process.

About Author :

I have been contributing in open source organization FOSSASIA, where I’m working on a project called BadgeYaY. It is a badge generator with a simple web UI to add data and generate printable badges in PDF.

Resources:

  • Heroku Pipelines Article – Link
Continue Reading Auto Deployment of Badgeyay Backend by Heroku Pipeline
Daimler: Our developers know about the advantages of Open Source Software
Mit fünf spektakulären Installationen hat Sarah Illenberger den Mercedes-Benz F015 Luxury in Motion in Szene gesetzt. Die renommierte Künstlerin arbeitete dabei im Spannungsfeld zwischen technologischer Zukunft und künstlerischer Handarbeit. Mit den Installationen übersetzte Illenberger die faszinierenden Eigenschaften des F015 in eine ausdrucksstarke Bildwelt, die dem Betrachter die Mercedes-Benz Vision vom autonomen Fahren näherbringt. Die Motive machen den Sprung in die neue Ära des Fahrens und die damit verbundenen Veränderungen begreifbar. Dabei wird automobile Ingenieurs- und Designleistung im besten Sinne zu Kunst. ; Sarah Illenberger has drawn attention to the Mercedes-Benz F015 Luxury in Motion by producing five spectacular installations. To do this, the renowned artist had to work between the poles of technological future and artistic handiwork. With these installations, Illenberger has translated the fascinating features of the F015 into an expressive pictorial world that brings the observer closer to the Mercedes-Benz vision of autonomous driving. The subjects take the leap into the new era of driving, rendering the associated changes touchable and comprehensible. This process sees automotive engineering and design achievements becoming art in the best sense of the word.;

Daimler: Our developers know about the advantages of Open Source Software

Vlado Koljibabic is Head of CASE IT at Daimler AG, the parent company of the car manufacturer Mercedes-Benz. He aims to strengthen the idea of Open Source in his company. Daimler is a partner of FOSSASIA. Torben Stephan interviewed Koljibabic on the advantages of open source software.

Stephan: What does CASE stand for?

Koljibabic: CASE is the combination of everything disruptive regarding our business: Connected, Autonomous, Shared & Services and Electric. These topics shall help us to transform from a car manufacturer to a mobility services provider. This is key in order to remain successful in the future.

How much Free and Open Source Software (FOSS) is actually part of a Mercedes?

We have been using FOSS for many years. Any Mercedes-Benz comes with a CD full of FOSS licenses. Every license belongs to a piece of open source software which is implemented in our cars. Even our Mercedes me app contains seven OS licenses. We use it because our developers know about the advantages of OSS.

Which are?

We don’t need to develop everything from scratch, we can reuse things where it makes sense and contribute to the development of open standards that increase efficiency throughout the system.

Daimler is a member of the “Automotive Grade Linux” (AGL) initiative initiated by the Linux Foundation. Isn’t that the right place for such open standards?

Absolutely. During FOSSASIA, with the community, we discussed the opportunity of defining an open standard for electric vehicle charging stations. From my point of view it definitely does make sense to develop this via the AGL. On the other hand Daimler might put even more commitment into this project to show we seriously want to be part of this.

Vlado Koljibabic CASE IT Daimler
Vlado Koljibabic CASE IT Daimler

 

What’s the advantage of open source software compared to proprietary?

Two things: Nobel Prize laureate John Nash showed that sharing of commodities brings advantages to all players in the market. For me this is the secret of the success of open source software. Beside this we can use existing software solutions for recurring processes. And the car industry is full of recurring processes. If there is no ready-to-use solution, we can initiate and design the processes and contribute to the community.

How do other business units within Daimler respond to this ideas?

For a company like Daimler these are huge changes. That’s why we do this step-by-step. First of all we convince our internal stakeholders of the reasonableness and the value of FOSS. As a following step we accelerate the topic within concrete projects. The overall process of enhancement of OSS usage is initiated and strategically supported. Jan Brecht the CIO of the Daimler AG drives and promotes the initiative essentially.

In which fields would you refrain from publishing your source code?

For example in highly sensitive areas in terms of competition. One example is Autonomous Driving – I would not be the first to focus on open source when it comes to this topic right now. But I’m sure that within the next years, there will be a deck of open source tools for Autonomous Driving, Machine Learning and Artificial Intelligence everyone can use.

Daimler uses a lot of open source. But what are you giving back to the community?

We are a member of the Linux Foundation and partner here at FOSSASIA. However, we don’t contribute source code yet in the context of open source projects. But we see the demand of the community and are working on it continuously to contribute as soon as possible.

Continue Reading Daimler: Our developers know about the advantages of Open Source Software

Unit Tests for REST-API in Python Web Application

Badgeyay backend is now shifted to REST-API and to test functions used in REST-API, we need some testing technology which will test each and every function used in the API. For our purposes, we chose the popular unit tests Python test suite.

In this blog, I’ll be discussing how I have written unit tests to test Badgeyay  REST-API.

First, let’s understand what is unittests and why we have chosen it. Then we will move onto writing API tests for Badgeyay. These tests have a generic structure and thus the code I mention would work in other REST API testing scenarios, often with little to no modifications.

Let’s get started and understand API testing step by step.

What is Unittests?

Unitests is a Python unit testing framework which supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections, and independence of the tests from the reporting framework. The unittest module provides classes that make it easy to support these qualities for a set of tests.

Why Unittests?

We get two primary benefits from unit testing, with a majority of the value going to the first:

  • Guides your design to be loosely coupled and well fleshed out. If doing test driven development, it limits the code you write to only what is needed and helps you to evolve that code in small steps.
  • Provides fast automated regression for re-factors and small changes to the code.
  • Unit testing also gives you living documentation about how small pieces of the system work.

We should always strive to write comprehensive tests that cover the working code pretty well.

Now, here is glimpse of how  I wrote unit tests for testing code in the REST-API backend of Badgeyay. Using unittests python package and requests modules, we can test REST API in test automation.

Below is the code snippet for which I have written unit tests in one of my pull requests.

def output(response_type, message, download_link):
    if download_link == '':
        response = [
            {
                'type': response_type,
                'message': message
            }
        ]
    else:
        response = [
            {
                'type': response_type,
                'message': message,
                'download_link': download_link
            }
        ]
    return jsonify({'response': response})

 

To test this function, I basically created a mock object which could simulate the behavior of real objects in a controlled way, so in this case a mock object may simulate the behavior of the output function and return something like an JSON response without hitting the real REST API. Now the next challenge is to parse the JSON response and feed the specific value of the response JSON to the Python automation script. So Python reads the JSON as a dictionary object and it really simplifies the way JSON needs to be parsed and used.

And here’s the content of the backend/tests/test_basic.py file.

 #!/usr/bin/env python3
"""Tests for Basic Functions"""
import sys
import json
import unittest

sys.path.append("../..")
from app.main import *


class TestFunctions(unittest.TestCase):
      """Test case for the client methods."""
    def setup(self):
        app.app.config['TESTING'] = True
        self.app = app.app.test_client()
      # Test of Output function
    def test_output(self):
        with app.test_request_context():
            # mock object
            out = output('error', 'Test Error', 'local_host')
            # Passing the mock object
            response = [
                {
                    'type': 'error',
                    'message': 'Test Error',
                    'download_link': 'local_host'
                }
            ]
            data = json.loads(out.get_data(as_text=True))
            # Assert response
            self.assertEqual(data['response'], response)


if __name__ == '__main__':
    unittest.main()

 

And finally, we can verify that everything works by running nosetests .

This is how I wrote unit tests in BadgeYaY repository. You can find more of work here.

Resources:

  • The Purpose of Unit Testing – Link
  • Unit testing framework – Link
Continue Reading Unit Tests for REST-API in Python Web Application

Parallelizing Builds In Travis CI

Badgeyay project is now divided into two parts i.e front-end of emberJS and back-end with REST-API programmed in Python. Now, one of the challenging job is that, it should support the uncoupled architecture. It should therefore run tests for the front-end and backend i.e, of two different languages on isolated instances by making use of the isolated parallel builds.

In this blog, I’ll be discussing how I have configured Travis CI to run the tests parallely in isolated parallel builds in Badgeyay in my Pull Request.

First let’s understand what is Parallel Travis CI build and why we need it. Then we will move onto configuring the travis.yml file to run tests parallely. Let’s get started and understand it step by step.

Why Parallel Travis CI Build?

The integration test suites tend to test more complex situations through the whole stack which incorporates front-end and back-end, they likewise have a tendency to be the slowest part, requiring various minutes to run, here and there even up to 30 minutes. To accelerate a test suite like that, we can split it up into a few sections utilizing Travis build matrix feature. Travis will decide the build matrix based on environment variables and schedule two builds to run.

Now our objective is clear that we have to configure travis.yml to build parallel-y. Our project requires two buildpacks, Python and node_js, running the build jobs for both them would speed up things by a considerable amount.It seems be possible now to run several languages in one .travis.yml file using the matrix:include feature.

Below is the code snippet of the travis.yml file  for the Badgeyay project in order to run build jobs in a parallel fashion.

sudo: required
dist: trusty

# check different combinations of build flags which is able to divide builds into “jobs”.
matrix:

# Helps to run different languages in one .travis.yml file
include:

# First Job in Python.
- language: python3

apt:
packages:
- python-dev

python:
- 3.5
cache:
directories:
- $HOME/backend/.pip-cache/

before_install:
- sudo apt-get -qq update
- sudo apt-get -y install python3-pip
- sudo apt-get install python-virtualenv

install:
- virtualenv  -p python3 ../flask_env
- source ../flask_env/bin/activate
- pip3 install -r backend/requirements/test.txt --cache-dir

before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sleep 3

script:
- python backend/app/main.py >> log.txt 2>&1  &
- python backend/app/main.py > /dev/null &
- py.test --cov ../  ./backend/app/tests/test_api.py

after_success:
- bash <(curl -s https://codecov.io/bash)

# Second Job in node js.
- language: node_js
node_js:
- "6"

addons:
chrome: stable

cache:
directories:
- $HOME/frontend/.npm

env:
global:
# See https://git.io/vdao3 for details.
- JOBS=1

before_install:
- cd frontend
- npm install
- npm install -g ember-cli
- npm i [email protected] --save-dev
- npm config set spin false

script:
- npm run lint:js
- npm test

 

Now, as we have added travis.yml and pushed it to the project repo. Here is the screenshot of passing Travis CI after parallel build jobs.

The related PR of this work is https://github.com/fossasia/badgeyay/pull/512

Resources :

Travis CI documentation – Link

Continue Reading Parallelizing Builds In Travis CI