How I made a GitHub action to host coding competition on GitHub!

jainal09

jainal gosaliya

Posted on April 16, 2020

How I made a GitHub action to host coding competition on GitHub!

Strivio Logo

Strivio

Strivio is a GitHub action that allows anyone to host competitive coding event directly on GitHub Repository like hackerrank, leetcode, etc. It is fun to use and quite simple. It also has the support of many programming languages such as c , c++, java and python
You can check Strivio here on the GitHub marketplace.
https://github.com/marketplace/actions/strivio
Strivio is also OpenSourced on GitHub and here are the links for the action and the source code of the action.
Action Repo - https://github.com/jainal09/strivio
Source Code- https://github.com/jainal09/strivio-docker
Also, check out the docker image on docker hub- https://hub.docker.com/r/jainal09/strivio

Introduction

Ever wondered that is it possible to host a competitive coding event on GitHub?
Well, it should be possible given the fact that GitHub provides CI / CD built-in through GitHub Action.
So, I decided wouldn't it be cool if I make a GitHub action that simply tests code by passing given sets of Inputs and checking it against given sets of outputs. Sounds simple right? Well, it's a kind of little complex!

enter image description here
You see, there are a few challenges I need to solve.

  • Input and output test cases should be hidden somewhere and the participants of the events cannot see it.
  • Multiple Programming Language Support
  • And a system that should enable organizers to use the action without modifying the code.
  • One GitHub action that can be used simultaneously many people around the world.

So, this is how it all went.

enter image description here

Idea Construction

So basically I created a rough idea of implementation like this:

my-python-script ------> user-code ------> compile and run ------> result

So, here first my python script identifies users' programming language. Then it compiles and runs the user's program by passing necessary inputs and storing outputs.
It then matches the outputs of the program with the output of the test cases. If all outputs are passed than tick
☑️ and if not than ✖️.

Solving Challenges

So, I thought if there is a way that input test cases magically appeared at run time and disappeared after that should solve my issue.

enter image description here

Hence, I used an amazing bash script known as the DropBox uploader.
https://github.com/andreafabrizi/Dropbox-Uploader
What it does is it allows anyone to download and upload files from their DropBox account from the terminal!
Sounds cool right. It also has many more cool features and I recommend you to have a look at this repository.
So, now organizers will simply upload input and output test cases on their DropBox drive and during the run time my script will download the input and output test cases through a unique token(dropbox API key) preventing visibility to the participants.
This solved my 2 challenges.

Input and output test cases should be hidden somewhere and the participants of the events cannot see it.

And a system that should enable organizers to use the action without modifying the code.

Still, 2 challenges needed to solve.
For multiple language support, I decided to stick it to simple and restrict the top 4 most popular competetive coding programming languages i.e python, java, cpp, and c.
enter image description here

The support to the programming languages can be solved by using docker with all the dependencies and compilers installed into a docker container.

Multiple Programming Language Support

enter image description here

And the last issue, allowing simultaneous use of action was solved by putting the DropBox API key as a GitHub secret and hence not hardcoding it in the code and hence anyone can use the action!

One GitHub action that can be used simultaneously many people around the world.

And that's how I solved all my challenges and issues.
enter image description here

Creating the action

So far the idea was clear to me and the challenges were so far sorted out.

Now it was coding time!
Enter fullscreen mode Exit fullscreen mode

enter image description here
As mentioned earlier I needed a python script which I will compile the code for me and a docker container.
Here Is the basic code segment from my Code : https://github.com/jainal09/strivio-docker/blob/master/Evaluate.py
Organizers will upload a I/O test cases and then I will download it and create into python arrays inputs and outputs. Then I will iterate them and compile and pass inputs and compare outputs. Check out the below code.

for inp, outp in zip(inputs, outputs):
     data, temp = os.pipe()
     os.write(temp, bytes(str(inp), "utf-8"))
     os.close(temp)
     output = subprocess.check_output(
         [
             "python3",
          os.path.abspath(
              "program.py"
          )
         ],
         stdin=data
     )
     output = output.decode("utf-8")
     output = re.sub('\s+', '', output)
     outp = re.sub('\s+', '', str(outp))                        
     if output == outp:
         print("Test Case " + str(case) + ": Passed")
         case = case + 1
     else:
         raise Exception(
             "Test Case " + str(case) + ": Failed"
         )
Enter fullscreen mode Exit fullscreen mode

Done its as simple as that! You can check out the whole code base and other cool stuff which I did here
https://github.com/jainal09/strivio-docker
I am not explaining here each and every segment of it as it kind of makes sense right!

Okay Now How do I use it?

Organizers

  1. Head to DropBox Sign In/ Create account and then click on this link DropBox Developer Page

Alternate Link: https://www.dropbox.com/developers/documentation

  • Click on App Console
  • Click on Create App
  • Click Full Dropbox
  • Give any name to the app and Click create app
    1. After you Create your Dropbox App click on Generate Access token and Copy it.enter image description here

This token is to be shared with participants. This works as a login access key for the competition.

  1. Create a File Known as 🗃️ "IO.yaml" for all the Input / Output Test Cases
  2. The File should Look like this
inputs:  
  input1:  
    1  
  input2:  
    2  
  input3:  
    3  
  input4:  
    4  
  input5:  
    5  
outputs:  
  output1:  
    2  
  output2:  
    3  
  output3:  
    4  
  output4:  
    5  
  output5:  
    6  
Enter fullscreen mode Exit fullscreen mode
  1. Head to DropBox, Upload this IO.yaml to the Root Directory (not into any folder just upload it outside on dropbox) of Drop Box and done 😃!
  2. Send the OATH token to participants.

Participants

  1. In GitHub Repo open Settings/Secrets and click on add a Secret
  2. The name of the secret should be OATH and value should be the access token which the organizer gave you!

Example:

Alt Text

This should look like this.

Alt Text

  1. Now its time to start coding! Clone your repo and start working on the problem.

  2. Supported Programming Languages python, java, c++, c

  3. Create a file program.extension - supported extension.c .cpp .java .py

NOTE: for java Class name should be Main

  1. After Coding is done create a file in repo 🗃️ "lang.yaml"

  2. Add the below code.

language:
  python3
Enter fullscreen mode Exit fullscreen mode
  1. Replace the name of Programming Language in the above code as follows.

python - write python3
java - write java
c++ - write cpp
c - write c

No language other than above are supported!

  1. Commit the code and push

  2. Head to GitHub and select Actions

Alt Text

  1. Click on Set up a workflow yourself

Alt Text

  1. Delete everything and paste the below code
name: Evaluation
on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Results
      uses: jainal09/strivio@Production
      with:
        oath: ${{ secrets.oath }}
Enter fullscreen mode Exit fullscreen mode

Click on start-commit

  1. Click on actions

Alt Text

  1. Click on your last commit, click build, wait for the Build jainal09/strivio@Production to turn green ✔️ and after that click on Results 🤞

Alt Text

  1. Check if your code passed all the Test Case ✔️ or ❌

Alt Text

☝️Successful Build with all Test Case Passed🤘.

Alt Text

☝️Build Failed as Code Didn't Pass all the Test Cases😬.

Sample Test Repo - https://github.com/jainal09/strivio-in-action

Done! that's how you can host a coding competition on GitHub like Hackerrank etc
enter image description here

What is the tech used here?

  • GitHub (obviously!)
  • GitHub actions
  • Python
  • Pyaml to parse the yaml files
  • Dropbox-Uploader
  • Docker
  • Docker Hub for Continuous Deployment with my GitHub repo.

Limitation and Future Scopes

As we all know there is nothing perfect in this world.
So does Strivio! As the idea is just a proof of concept and not a competitor to the online coding platforms.
enter image description here

The following are the Limitations of the project:

Currently, only 1 question per repo is supported and I am working for more project support.

  • I believe that input and output test cases format should be improved and also separated into 2 different txt files rather than yaml.
  • Timing and space constraint features are not present.
  • Testing against complex I/O test cases.

The following are the Future Scopes of the project:

  • [ ] Add support for time and space constraints.
  • [ ] Change Input output formats.
  • [ ] And offcourse solve any created issues.
💖 💪 🙅 🚩
jainal09
jainal gosaliya

Posted on April 16, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related