Coder Social home page Coder Social logo

meeseeksdev's Introduction

MeeseeksBox

A base for stateless GitHub Bot,and one hosted implementation thereof.

See what is a Meeseeks and a MeeseeksBox.

See usage statistics.

Hosted for you

We host MeeseeksBox(es) and will expose them as GitHub Integrations so you don't have to host and run your own. You can if you want, it should be pretty simple.

The advantage of having one and only one box, is to do cross repository operations (and fix security bugs).

The drawback is if there is a security issue, then we're screwed.

Activate on your Repo

  1. Head there and activate MeeseeksDev on repos you have access to.

  2. On a repository with MeeseeksDev installed say: @MeeseeksDev Hello to be sure MeeseeksDev is correctly installed.

  3. Enjoy

You might also want to tell your CI-integration (like travis-ci) not to test the push and the merge. To do so use:

branches:
  except:
    - /^auto-backport-of-pr-[0-9]+$/

per-repository configuration

If you want per-repository configuration, create a .meeseeksdev.yml file at the root of the repository. For now this file allow you to give fine-grained permissions to users.

users:
  <username>:
    can:
      - <command 1>
      - <command 2>
      - ...
  <username>
    can:
      - ...

This will allow <username> to ask @meeseeksdev to perform above commands. The conf file is the one that sits on the repository default branch (usually master).

What can a MeeseeksBox do ?

Comment on a Pr or issue.

You may put multiple commands, one per line.

MrMeeseeks may not like what you ask, and just ignore you.

@MeeseeksDev hello

Respond with

Hello {user} look at me, I'm Mr Meeseeks

To test whether a Meeseeks understand you.

@MeeseeksDev backport [to] {branch}

If issued from a PR which is merged, attempt to backport (cherry-pick the merge commit) on an older branch and submit a PR with this backport (on said branch)

Apply origin-pr labels and milestone to backport.

  • No option to push directly (yet), if implemented should apply only with clean backport.
  • Investigate what to do in case of conflict
    • likely commit with conflict, and let maintainers resolve conflict

Repo admins only

Note: Cloning can take a long-time. So expect MrMeeseeks to be busy while this happen. Also heroku has a 2min deadline and other limitations, so MrMeeseeks can likely be killed. I haven't implemented a queue yet.

@MeeseeksDev black

If issued from a PR, will apply black to commits made in this PR and push the updated commits.

You can also use "blackify" as an alias.

Repo admins only, we plan to make it available to PR authors as well.

MeeseeksDev Bot needs to be installed on the PR source repository for this to work. If it's not it will ask you to do so.

@MeeseeksDev pre-commit

If issued from a PR, will apply pre-commit to this PR and push a commit with the changes made. If no changes are made, or the changes cannot be automatically fixed, it will show a comment in the PR and bail.

You can also use "precommit" as an alias.

Repo admins only, we plan to make it available to PR authors as well.

MeeseeksDev Bot needs to be installed on the PR source repository for this to work. If it's not it will ask you to do so.

@MeeseeksDev pep8ify

(in progress)

If issued from a PR, will apply autopep8 to the current lines changed by this PR, and push an extra commit to it that fixes pep8.

Code in progress and due to GitHub API limitation only works if MeeseeksDev also available on Source repo of the PR.

Repo admins only, plan to make it available to PR author as well.

MeeseeksDev Bot need to be installed on the PR source repository for this to work. If it's not it will ask you to do so.

@MeeseeksDev migrate [to] {target org/repo}

Needs MeeseeksBox to be installed on both current and target repo. Command issuer to be admin on both.

MeeseeksDev will open a similar issue, replicate all comments with links to first, migrate labels (if possible).

@MeeseeksDev close

Close the issue. Useful when replying by mail

@MeeseeksDev open

Reopen the issue.

@MeeseeksDev tag {comma, separated, case sensitive, taglist}

Tag with said tags if availlable (comma separated, need to be exact match)

@MeeseeksDev untag {comma, separated, case sensitive, taglist}

Remove said tags if present (comma separated, need to be exact match)

@MeeseeksDev merge [merge|squash|rebase]

Issuer needs at least write permission.

If Mergeable, Merge current PR using said methods (merge if no arguments)

Command Extras

You can be polite and use "please" with any of the commands, e.g. "@Meeseeksdev please close".

You can optionally use the word "run" in the command, e.g. "@Meeseeksdev please run pre-commit".

Simple extension.

Most extension and new command for the MeeseeksBox are only one function, for example here is how to let everyone request the zen of Python:

from textwrap import dedent

@everyone
def zen(*, session, payload, arguments):
    comment_url     = payload['issue']['comments_url']
    session.post_comment(comment_url,
    dedent(
        """
        Zen of Python ([pep 20](https://www.python.org/dev/peps/pep-0020/))
        ```
        >>> import this
        Beautiful is better than ugly.
        Sparse is better than dense.
        ....
        Although never is often better than *right* now.
        Namespaces are one honking great idea -- let's do more of those!
        ```
        """
    ))

The session object is authenticated with the repository the command came from. If you need to authenticate with another repository with MeeseeksBox installed yield the org/repo slug.

@admin
def foo(*, session, payload, argument):
    other_session = yield 'MeeseeksBox/MeeseeksBox'
    if other_session:
        print('you are allowed to access MeeseeksBox/MeeseeksBox')
        other_session.do_stuff()
    else:
        session.post_comment("Sorry Jerry you are not allowed to do that.")

Why do you request so much permission ?

GitHub API does not allow to change permissions once given (yet). We don't want you to go though the process of reinstalling all integrations.

We would like to request less permission if necessary.

Setup.

See CONTIBUTING.md for for information.

Warnings

This is still alpha software, user and org that can use it are still hardcoded. If you want access open an issue for me to allowlist your org and users.

Because of GitHub API limitation, MeeseeksBox can not yet make the distinction between read-only and read-write collaborators.

Addons

heroku addons:create keen

Changelog

  • 2017-10-31: Backport now support squash-merge

meeseeksdev's People

Contributors

carreau avatar blink1073 avatar dependabot[bot] avatar dependabot-support avatar dependabot-preview[bot] avatar qulogic avatar pllim avatar tacaswell avatar jasonweill avatar neutrinoceros avatar stanczakdominik avatar larsoner avatar fcollonval avatar krassowski avatar saimn avatar

Stargazers

Marcus Hughes avatar Maxim Zaslavsky avatar Thomas Li avatar Nikolaus Schlemm avatar Jeremy Tuloup avatar chanakin avatar Christian Kasim Loan avatar Rosio avatar martinRenou avatar Gonzalo Peña-Castellanos avatar Anirrudh Krishnan avatar Saul Shanabrook avatar Matthew Feickert avatar Christian Hudon avatar moueza avatar Ian Rose avatar Thomas Robitaille avatar  avatar  avatar Sourav Singh avatar DAVID RUPP JR. avatar Hassan Kibirige avatar David Pérez-Suárez avatar Patrick Connolly avatar Carol Willing avatar  avatar Logan avatar Jessica B. Hamrick avatar Philipp Rudiger avatar John Detlefs avatar  avatar Brian E. Granger avatar  avatar

Watchers

Jarrod Millman avatar  avatar  avatar Juan Nunez-Iglesias avatar James Cloos avatar Logan avatar  avatar Matthew Feickert avatar  avatar Brigitta Sipőcz avatar

meeseeksdev's Issues

bot not responding to backport label?

Hello. The bot has been working great until recently. I noticed at astropy/astropy#13108 that it is not triggered by the backport-v5.0.x label anymore, which used to work. Can you please check your bot logs and let me know what is going on? Has the procedure changed?

Have a way to tell bot to rebase its PR

Hello. Thanks for the awesome bot!

We ran into a situation where bot has a few backport PRs open but one of them fixes the CI for the rest. If we merge that one first, is there a way to tell the bot to rebase (not pull) its other PRs on the same repo to pick up that fix?

Assigning projects

In Astropy we've been enjoying using MeeseeksDev. I use a project board to track and categorize my PRs, current and intended. When A PR in the project is backported using MeeseeksDev, it would be great if the backport PR were automatically added to the project.

Originally mentioned in: astropy/astropy#12656 (comment)

Debug Matplotlib issues.

@QuLogic you should be able to push changes and view logs via herokuCLI tool or using the browser based papertrail addon.

things seem to be wrong in core.py ~ line 212:

    print('[DEBUG] description:', description)
    print('[DEBUG] base ref:', is_pr['base']['ref'])
    if 'on-merge:' in description and is_pr['base']['ref'] == 'master':  #THIS <<<<<
        print('[DEBUG] on merge detected')
        for l in description.splitlines():
            print('[DEBUG] testing line...:{}'.format(l))
            if l.startswith('on-merge:'): ## OR THIS <<<<<<<
                todo = l[len('on-merge:'):].strip()
                print('After Merged in master; should:', todo)
                self.dispatch_on_mention('@meeseeksdev '+todo, payload, merged_by['login'])

If you push a commit on this repo it should automatically be deployed.

Backport without requiring push permission.

I want to upgrade Mr. Meeseeks to not require push-permissions to repositories for many reason:

  1. Security
  2. not clutter repos with branches named backport-pr-XXX-to-YYYY.

Thus I've created a meeseeksmachine GitHub Machine account it's like a personal account but have no human activity. With the creds of this account, I can fork, and make cross-organisation PRs, which Mr Meeseks couldn't do before due to GitHub limitation..

Using the new safe_backport, Mr Meeseeks can now backport without touching the target repository. The backport PR is created by, and come from the @meeseeksmachine account, like in this PR, @meeseeksdev is still responsible for the rest.

if you want to try it now

Change backport to safe_backport and report any potential bugs.

In the future I'll switch the backport to use the new mechanism, and remove the requirement for push permission.

[command] sed like.

On a PR if a line with @mention sed /pattern/replace/ is issued auto apply this on the PR and push the patch.

conflict in backport break fast-forward optimisation.

When backporting the bot attempt to reuse previous clone and just do a pull.
This can fail, and then erase the full-repository and re-clone.

One of the case where this can fail, is when the previous backport did not apply cleanly and the merge conflict has not been resolved.

When this is the case we should try to cleanup the merge conflict.

Does Mr. MeeseeksDev like pandas?

If so, would he mind handling backports for us? :)

The pandas-people to add would be

  • jreback
  • jorisvandenbossche
  • gfyoung
  • TomAugspurger

Any other info you need? Our backports branches are named as 0.20.x for the backports that should go from master to 0.20.1, 0.20.2, etc.

Thanks!

Allow for a trailing period in the backport request

Quite frequently I have typed the command as sentence, e.g. please backport to 1.2.x.. The trailing period confuses our friend. It would be nice for him to be able to try the branch as-is, and then try removing a trailing dot if there is one.

Add context message when cherry-picking?

Should we add the -x option when cherry-picking?

"When recording the commit, append a line that says "(cherry picked from commit …​)" to the original commit message in order to indicate which commit this change was cherry-picked from."

[command] As issue

When commenting on a PR, we could use a @mention as issue, to turn the comment into an issue to address later.

Decrease bot permission

One of the goal for mr meeseeks is to not have write permission to repositories for security reason as most actions are done via the meeseeksmachine user though it currently have write permission via "content".

Contents 
Repository contents, commits, branches, downloads, releases, and merges.

But also only to "pull requests"

Pull requests 
Pull requests and related comments, assignees, labels, milestones, and merges.

See https://github.com/organizations/MeeseeksBox/settings/apps/meeseeksdev/permissions if you have access.

I'd like to discuss what we can do to disable global write access to content, and which action it can perform that would be affected. For example I don't know if code reformatting on PR requires "content" access or "Pull requests" access.

Use for Astropy

Hi @Carreau,

We would like to use @meeseeksdev to backport PRs for Astropy. We are currently testing it, we installed the app and @meeseeksdev seems to be already responding to our comments, and it looks great ! Thanks for the tool.
I'm reaching you as it seems you have a whitelist of users/orgs, and I'm not sure if something needs to be done here ?

Also is there a way to add specific labels on backported PRs ? I found a mention of something similar, on-merge: say "Oh Weeeee", so I'm guessing we could use on-merge: tag some-label ? (Not sure if this would apply to the backport PR though ?)

'list' object has no attribute 'raise_if_error'

[1](https://my.papertrailapp.com/events?q=program%3Aapp%2Fweb.1&focus=1450275378027352064&selected=1450275378027352064) Traceback (most recent call last):
Apr 11 22:43:37 [meeseeksbot](https://my.papertrailapp.com/systems/meeseeksbot/events?focus=1450275378027352065&selected=1450275378027352065) [app/web.1](https://my.papertrailapp.com/events?q=program%3Aapp%2Fweb.1&focus=1450275378027352065&selected=1450275378027352065)   File "/app/meeseeksdev/meeseeksbox/commands.py", line 964, in safe_backport
Apr 11 22:43:37 [meeseeksbot](https://my.papertrailapp.com/systems/meeseeksbot/events?focus=1450275378027352066&selected=1450275378027352066) [app/web.1](https://my.papertrailapp.com/events?q=program%3Aapp%2Fweb.1&focus=1450275378027352066&selected=1450275378027352066)     ).raise_if_error()
Apr 11 22:43:37 [meeseeksbot](https://my.papertrailapp.com/systems/meeseeksbot/events?focus=1450275378027352067&selected=1450275378027352067) [app/web.1](https://my.papertrailapp.com/events?q=program%3Aapp%2Fweb.1&focus=1450275378027352067&selected=1450275378027352067) AttributeError: 'list' object has no attribute 'raise_if_error'
Apr 11 22:43:37 [meeseeksbot](https://my.papertrailapp.com/systems/meeseeksbot/events?focus=1450275378027352068&selected=1450275378027352068) [app/web.1](https://my.papertrailapp.com/events?q=program%3Aapp%2Fweb.1&focus=1450275378027352068&selected=1450275378027352068)     [backport] could not push to self remote
Apr 11 22:43:37 [meeseeksbot](https://my.papertrailapp.com/systems/meeseeksbot/events?focus=1450275378027352069&selected=1450275378027352069) [app/web.1](https://my.papertrailapp.com/events?q=program%3Aapp%2Fweb.1&focus=1450275378027352069&selected=1450275378027352069) Making a POST call to https://api.github.com/repos/matplotlib/matplotlib/issues/22807/comments
Apr 11 22:43:38 [meeseeksbot](https://my.papertrailapp.com/systems/meeseeksbot/events?focus=1450275381838278659&selected=1450275381838278659) [app/web.1](https://my.papertrailapp.com/events?q=program%3Aapp%2Fweb.1&focus=1450275381838278659&selected=1450275381838278659)     [backport] 'list' object has no attribute 'raise_if_error'

@blink1073

Backport and milestone

@choldgraf and @tacaswell, about auto backport:

What about a mini-language in milestone description, something in the milestone description(editable on GitHub) that tell the bots which branches to backport to; Something like:

- backport: v2.x

Allowing potentially multiple - backport: targets.

Thoughts ?

[command] Restart test

Have a command that restart failed test if requested by author or admin.
Will need travis integration.

Automatically set milestones on merged PRs

One issue we have a lot is that merged PRs are assigned to the wrong milestones. For example, a PR was originally assigned to a milestone, then merged earlier or later than that milestone, or a PR was merged with no milestone.

Just brainstorming here: it would great if there was some way to automatically set the appropriate milestone when a PR is merged. For example, if a PR was merged into a backport branch, it could be assigned to the appropriate previous release milestone, or if a PR was merged into master, even if it had a different milestone already set, it could be reassigned to an appropriate milestone.

It seems that the tricky thing here is deciding what the appropriate milestone is. Perhaps the easiest way to do it is to check what branch it was merged into, and somewhere have a table of branches to milestones. Or maybe even more appropriate is to have a revision spec (like master --not 0.34) for each milestone, i.e., take the merge commit from the PR, and check to see if it is each revision spec, and the first revision spec to win is the milestone to assign. Of course, you'd want to be able to update these tables, so perhaps they could be stored in a file in the repo? Does meeseeks have access to files in the repo? (And if so, which version of the file should be used? Probably just the one at the tip of master?)

I'm not quite sure how it could work out, but it would be wonderful if this could be automated. We're very often making errors, which makes the release process full of tedious work to check the PRs in the milestone against the actual merged commits.

Feature: Grab CircleCI docs

The scikit-learn devs use a nifty chrome extension to create a link to the documentation for a project built with CircleCI. Perhaps this is something that meeseeks could handle.

Circle exposes a list of artifacts with this API:

https://circleci.com/api/v1.1/project/github/:org/:project/:build/artifacts

e.g. this gets a list of artifacts from the latest build on the team-compass repo:

https://circleci.com/api/v1.1/project/github/jupyterhub/team-compass/latest/artifacts

returns something like:

[ {
  "path" : "html/.buildinfo",
  "pretty_path" : "html/.buildinfo",
  "node_index" : 0,
  "url" : "https://11-113493831-gh.circle-artifacts.com/0/html/.buildinfo"
}, {
  "path" : "html/index.html",
  "pretty_path" : "html/index.html",
  "node_index" : 0,
  "url" : "https://11-113493831-gh.circle-artifacts.com/0/html/index.html"
},
...

The result is a list of JSON w/ the name/path for each artifact.

Perhaps meeseeks could have a command like

@MeeseeksDev get-circle-artifact /path/to/artifact

Meeseeks would:

  1. Use the org/repo from the current PR page
  2. Figure out the build number for the PR (somehow)
  3. Ask for the list of artifacts for this build
  4. Look for the artifact that matches this file path
  5. Post a comment with a link to the artifact

WDYT?

Migration Error

cf jupyter/nb2kg#51 (comment)

2022-03-29T14:40:22.789507+00:00 app[web.1]: found permission admin for user  kevin-bates on  jupyter-server enterprise_gateway

2022-03-29T14:40:22.789924+00:00 app[web.1]: ERROR:tornado.application:Uncaught exception POST /webhook (10.1.45.64)

2022-03-29T14:40:22.789926+00:00 app[web.1]: HTTPServerRequest(protocol='http', host='meeseeksbot.herokuapp.com', method='POST', uri='/webhook', version='HTTP/1.1', remote_ip='10.1.45.64')

2022-03-29T14:40:22.789927+00:00 app[web.1]: Traceback (most recent call last):

2022-03-29T14:40:22.789941+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.10/site-packages/tornado/web.py", line 1702, in _execute

2022-03-29T14:40:22.789942+00:00 app[web.1]:     result = method(*self.path_args, **self.path_kwargs)

2022-03-29T14:40:22.789942+00:00 app[web.1]:   File "/app/meeseeksdev/meeseeksbox/core.py", line 211, in post

2022-03-29T14:40:22.789942+00:00 app[web.1]:     return self.dispatch_action(action, payload)

2022-03-29T14:40:22.789942+00:00 app[web.1]:   File "/app/meeseeksdev/meeseeksbox/core.py", line 297, in dispatch_action

2022-03-29T14:40:22.789943+00:00 app[web.1]:     self.dispatch_on_mention(body, payload, user)

2022-03-29T14:40:22.789943+00:00 app[web.1]:   File "/app/meeseeksdev/meeseeksbox/core.py", line 589, in dispatch_on_mention

2022-03-29T14:40:22.789943+00:00 app[web.1]:     gen.send(target_session)

2022-03-29T14:40:22.789944+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.10/site-packages/yieldbreaker/__init__.py", line 61, in send

2022-03-29T14:40:22.789944+00:00 app[web.1]:     self._next = self._gen.send(value)

2022-03-29T14:40:22.789944+00:00 app[web.1]:   File "/app/meeseeksdev/commands.py", line 106, in migrate_issue_request

2022-03-29T14:40:22.789944+00:00 app[web.1]:     fix_issue_body(

2022-03-29T14:40:22.789945+00:00 app[web.1]:   File "/app/meeseeksdev/meeseeksbox/utils.py", line 74, in fix_issue_body

2022-03-29T14:40:22.789945+00:00 app[web.1]:     return (

2022-03-29T14:40:22.789945+00:00 app[web.1]: KeyError: 'prefix'

Using MeeseeksDev in scvi-tools

Hi @Carreau We're trying to set up MeeseeksDev to use it for automatic backporting in scvi-tools. The issue I'm running into is that the bot keeps complaining about the target branch not existing (see here for my attempts). I created a test branch (msdtest) off of an older commit on our master branch and am trying to use the bot to backport the newest commit on master to msdtest. However the bot cannot find the branch.

Digging into MeeseeksMachine, it looks like the fork of our repo on that org doesn't have the new branches I create. That might explain why the bot cannot find the target branch. Do I need to do something to keep the fork in sync, or else what am I doing wrong?

[command] Pep8ify

Right now it can't because of limitation of GitHub api.

Follow Up with GitHub or ask the user to install the integration on their repo.

Deploy for Matplotlib

This was requested on the mailing list. I've already pushed commit that should handle that, the only "optimisation" we could do is pre-clone the matplotlib repository, because it can be slow to get the first time, and switch from a "git clone" to a "git fetch" , "git reset --hard origin/master" to gain some time during the backport.

cc @choldgraf

handle squash-merge and rebase-merge PR

Trying to cherry-pick a squash-merge results in errors like:

ct 29 18:13:42 meeseeksbot app/web.1:  ---------------------------------------- 
Oct 29 18:13:42 meeseeksbot app/web.1:  == Cleaning up previsous work...  
Oct 29 18:13:42 meeseeksbot app/web.1:  == Done cleaning  
Oct 29 18:13:42 meeseeksbot app/web.1:  == Cloning current repository, this can take some time.. 
Oct 29 18:13:42 meeseeksbot app/web.1:  Cloning into 'matplotlib'... 
Oct 29 18:14:01 meeseeksbot heroku/router:  at=error code=H12 desc="Request timeout" method=POST path="/webhook" host=meeseeksbot.herokuapp.com request_id=d4ba2128-42d2-4c89-8a09-ae8477213779 fwd="192.30.252.42" dyno=web.1 connect=1ms service=30003ms status=503 bytes=0 protocol=https 
Oct 29 18:14:10 meeseeksbot heroku/router:  at=error code=H12 desc="Request timeout" method=POST path="/webhook" host=meeseeksbot.herokuapp.com request_id=0c8e8fdc-b76b-424e-9a9c-fdd42f235091 fwd="192.30.252.34" dyno=web.1 connect=1ms service=30001ms status=503 bytes=0 protocol=https 
Oct 29 18:14:14 meeseeksbot heroku/router:  at=error code=H12 desc="Request timeout" method=POST path="/webhook" host=meeseeksbot.herokuapp.com request_id=5c574610-0b16-430f-af2e-3e024888df19 fwd="192.30.252.45" dyno=web.1 connect=0ms service=30001ms status=503 bytes=0 protocol=https 
Oct 29 18:14:23 meeseeksbot app/web.1:  == Cloned.. 
Oct 29 18:14:23 meeseeksbot app/web.1:  == Fetching branch to backport on ... 
Oct 29 18:14:24 meeseeksbot app/web.1:  == Fetching Commits to backport... 
Oct 29 18:14:24 meeseeksbot app/web.1:  == All has been fetched correctly 
Oct 29 18:14:24 meeseeksbot app/web.1:  Cherry-picking 6aeeec7efde2c9dfacf88d27118c7507002af4c7 
Oct 29 18:14:24 meeseeksbot app/web.1:    stderr: 'error: Mainline was specified but commit 6aeeec7efde2c9dfacf88d27118c7507002af4c7 is not a merge. 
Oct 29 18:14:24 meeseeksbot app/web.1:  fatal: cherry-pick failed' 

Falling back to without -m 1 would work in this case, but would likely fail in interesting ways for rebase-merge.

Split Framework/commands/deployment

This repo currently have 3 things.

The main framework (mostly in __init__.py and utils.py).
A bunch a predefined commands (in commands.py)
And the deployment itself. Part of requirement + Heroku specific files.

It should be splitted in 3 parts/repo.

TEST

Figure out how. Probably mock the request reply.

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.