{"id":22313806,"url":"https://github.com/ctb/pony-build","last_synced_at":"2025-07-29T10:32:39.095Z","repository":{"id":42788904,"uuid":"259572","full_name":"ctb/pony-build","owner":"ctb","description":"A simple continuous integration system, written in Python.","archived":false,"fork":false,"pushed_at":"2010-04-24T04:20:41.000Z","size":1595,"stargazers_count":86,"open_issues_count":11,"forks_count":11,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-05T11:11:30.407Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://wiki.github.com/ctb/pony-build","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ctb.png","metadata":{"files":{"readme":"README.html","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2009-07-24T13:59:59.000Z","updated_at":"2024-02-27T08:00:33.000Z","dependencies_parsed_at":"2022-09-01T17:51:48.967Z","dependency_job_id":null,"html_url":"https://github.com/ctb/pony-build","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ctb/pony-build","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctb%2Fpony-build","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctb%2Fpony-build/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctb%2Fpony-build/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctb%2Fpony-build/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ctb","download_url":"https://codeload.github.com/ctb/pony-build/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ctb%2Fpony-build/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267670386,"owners_count":24125130,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-03T22:08:15.572Z","updated_at":"2025-07-29T10:32:38.558Z","avatar_url":"https://github.com/ctb.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c?xml version=\"1.0\" encoding=\"utf-8\" ?\u003e\n\u003c!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"\u003e\n\u003chtml xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"\u003e\n\u003chead\u003e\n\u003cmeta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /\u003e\n\u003cmeta name=\"generator\" content=\"Docutils 0.4: http://docutils.sourceforge.net/\" /\u003e\n\u003ctitle\u003epony-build\u003c/title\u003e\n\u003cstyle type=\"text/css\"\u003e\n\n/*\n:Author: David Goodger\n:Contact: goodger@users.sourceforge.net\n:Date: $Date: 2005-12-18 01:56:14 +0100 (Sun, 18 Dec 2005) $\n:Revision: $Revision: 4224 $\n:Copyright: This stylesheet has been placed in the public domain.\n\nDefault cascading style sheet for the HTML output of Docutils.\n\nSee http://docutils.sf.net/docs/howto/html-stylesheets.html for how to\ncustomize this style sheet.\n*/\n\n/* used to remove borders from tables and images */\n.borderless, table.borderless td, table.borderless th {\n  border: 0 }\n\ntable.borderless td, table.borderless th {\n  /* Override padding for \"table.docutils td\" with \"! important\".\n     The right padding separates the table cells. */\n  padding: 0 0.5em 0 0 ! important }\n\n.first {\n  /* Override more specific margin styles with \"! important\". */\n  margin-top: 0 ! important }\n\n.last, .with-subtitle {\n  margin-bottom: 0 ! important }\n\n.hidden {\n  display: none }\n\na.toc-backref {\n  text-decoration: none ;\n  color: black }\n\nblockquote.epigraph {\n  margin: 2em 5em ; }\n\ndl.docutils dd {\n  margin-bottom: 0.5em }\n\n/* Uncomment (and remove this text!) to get bold-faced definition list terms\ndl.docutils dt {\n  font-weight: bold }\n*/\n\ndiv.abstract {\n  margin: 2em 5em }\n\ndiv.abstract p.topic-title {\n  font-weight: bold ;\n  text-align: center }\n\ndiv.admonition, div.attention, div.caution, div.danger, div.error,\ndiv.hint, div.important, div.note, div.tip, div.warning {\n  margin: 2em ;\n  border: medium outset ;\n  padding: 1em }\n\ndiv.admonition p.admonition-title, div.hint p.admonition-title,\ndiv.important p.admonition-title, div.note p.admonition-title,\ndiv.tip p.admonition-title {\n  font-weight: bold ;\n  font-family: sans-serif }\n\ndiv.attention p.admonition-title, div.caution p.admonition-title,\ndiv.danger p.admonition-title, div.error p.admonition-title,\ndiv.warning p.admonition-title {\n  color: red ;\n  font-weight: bold ;\n  font-family: sans-serif }\n\n/* Uncomment (and remove this text!) to get reduced vertical space in\n   compound paragraphs.\ndiv.compound .compound-first, div.compound .compound-middle {\n  margin-bottom: 0.5em }\n\ndiv.compound .compound-last, div.compound .compound-middle {\n  margin-top: 0.5em }\n*/\n\ndiv.dedication {\n  margin: 2em 5em ;\n  text-align: center ;\n  font-style: italic }\n\ndiv.dedication p.topic-title {\n  font-weight: bold ;\n  font-style: normal }\n\ndiv.figure {\n  margin-left: 2em ;\n  margin-right: 2em }\n\ndiv.footer, div.header {\n  clear: both;\n  font-size: smaller }\n\ndiv.line-block {\n  display: block ;\n  margin-top: 1em ;\n  margin-bottom: 1em }\n\ndiv.line-block div.line-block {\n  margin-top: 0 ;\n  margin-bottom: 0 ;\n  margin-left: 1.5em }\n\ndiv.sidebar {\n  margin-left: 1em ;\n  border: medium outset ;\n  padding: 1em ;\n  background-color: #ffffee ;\n  width: 40% ;\n  float: right ;\n  clear: right }\n\ndiv.sidebar p.rubric {\n  font-family: sans-serif ;\n  font-size: medium }\n\ndiv.system-messages {\n  margin: 5em }\n\ndiv.system-messages h1 {\n  color: red }\n\ndiv.system-message {\n  border: medium outset ;\n  padding: 1em }\n\ndiv.system-message p.system-message-title {\n  color: red ;\n  font-weight: bold }\n\ndiv.topic {\n  margin: 2em }\n\nh1.section-subtitle, h2.section-subtitle, h3.section-subtitle,\nh4.section-subtitle, h5.section-subtitle, h6.section-subtitle {\n  margin-top: 0.4em }\n\nh1.title {\n  text-align: center }\n\nh2.subtitle {\n  text-align: center }\n\nhr.docutils {\n  width: 75% }\n\nimg.align-left {\n  clear: left }\n\nimg.align-right {\n  clear: right }\n\nol.simple, ul.simple {\n  margin-bottom: 1em }\n\nol.arabic {\n  list-style: decimal }\n\nol.loweralpha {\n  list-style: lower-alpha }\n\nol.upperalpha {\n  list-style: upper-alpha }\n\nol.lowerroman {\n  list-style: lower-roman }\n\nol.upperroman {\n  list-style: upper-roman }\n\np.attribution {\n  text-align: right ;\n  margin-left: 50% }\n\np.caption {\n  font-style: italic }\n\np.credits {\n  font-style: italic ;\n  font-size: smaller }\n\np.label {\n  white-space: nowrap }\n\np.rubric {\n  font-weight: bold ;\n  font-size: larger ;\n  color: maroon ;\n  text-align: center }\n\np.sidebar-title {\n  font-family: sans-serif ;\n  font-weight: bold ;\n  font-size: larger }\n\np.sidebar-subtitle {\n  font-family: sans-serif ;\n  font-weight: bold }\n\np.topic-title {\n  font-weight: bold }\n\npre.address {\n  margin-bottom: 0 ;\n  margin-top: 0 ;\n  font-family: serif ;\n  font-size: 100% }\n\npre.literal-block, pre.doctest-block {\n  margin-left: 2em ;\n  margin-right: 2em ;\n  background-color: #eeeeee }\n\nspan.classifier {\n  font-family: sans-serif ;\n  font-style: oblique }\n\nspan.classifier-delimiter {\n  font-family: sans-serif ;\n  font-weight: bold }\n\nspan.interpreted {\n  font-family: sans-serif }\n\nspan.option {\n  white-space: nowrap }\n\nspan.pre {\n  white-space: pre }\n\nspan.problematic {\n  color: red }\n\nspan.section-subtitle {\n  /* font-size relative to parent (h1..h6 element) */\n  font-size: 80% }\n\ntable.citation {\n  border-left: solid 1px gray;\n  margin-left: 1px }\n\ntable.docinfo {\n  margin: 2em 4em }\n\ntable.docutils {\n  margin-top: 0.5em ;\n  margin-bottom: 0.5em }\n\ntable.footnote {\n  border-left: solid 1px black;\n  margin-left: 1px }\n\ntable.docutils td, table.docutils th,\ntable.docinfo td, table.docinfo th {\n  padding-left: 0.5em ;\n  padding-right: 0.5em ;\n  vertical-align: top }\n\ntable.docutils th.field-name, table.docinfo th.docinfo-name {\n  font-weight: bold ;\n  text-align: left ;\n  white-space: nowrap ;\n  padding-left: 0 }\n\nh1 tt.docutils, h2 tt.docutils, h3 tt.docutils,\nh4 tt.docutils, h5 tt.docutils, h6 tt.docutils {\n  font-size: 100% }\n\ntt.docutils {\n  background-color: #eeeeee }\n\nul.auto-toc {\n  list-style-type: none }\n\n\u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003cdiv class=\"document\" id=\"pony-build\"\u003e\n\u003ch1 class=\"title\"\u003epony-build\u003c/h1\u003e\n\u003cp\u003epony-build is a simple continuous integration package that lets you\nrun a server to display client build results.  It consists of two\ncomponents, a server (which is run in some central \u0026amp; accessible\nlocation), and one or more clients (which must be able to contact the\nserver via HTTP).\u003c/p\u003e\n\u003cp\u003ePhilosophy statement: good development tools for Python should be easy\nto install, easy to hack, and not overly constraining.  Two out of\nthree ain't bad ;).\u003c/p\u003e\n\u003cp\u003eThe pony-build architectural model is this: use decoupled components\nthat communicate via webhooks whenever possible.\u003c/p\u003e\n\u003cp\u003eAlso see \u003ca class=\"reference\" href=\"http://buildbot.sf.net/\"\u003ebuildbot\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch1\u003e\u003ca id=\"links\" name=\"links\"\u003eLinks\u003c/a\u003e\u003c/h1\u003e\n\u003cp\u003epony-build is hosted on github.\u003c/p\u003e\n\u003cp\u003epony-build central repository: \u003ca class=\"reference\" href=\"http://github.com/ctb/pony-build\"\u003ehttp://github.com/ctb/pony-build\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003epony-build issue tracking: \u003ca class=\"reference\" href=\"http://github.com/ctb/pony-build/issues\"\u003ehttp://github.com/ctb/pony-build/issues\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003epony-build wiki: \u003ca class=\"reference\" href=\"http://wiki.github.com/ctb/pony-build\"\u003ehttp://wiki.github.com/ctb/pony-build\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003epony-build mailing list: \u003ca class=\"reference\" href=\"http://lists.idyll.org/listinfo/pony-build\"\u003ehttp://lists.idyll.org/listinfo/pony-build\u003c/a\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch1\u003e\u003ca id=\"requirements\" name=\"requirements\"\u003eRequirements\u003c/a\u003e\u003c/h1\u003e\n\u003cdl class=\"docutils\"\u003e\n\u003cdt\u003eServer side:\u003c/dt\u003e\n\u003cdd\u003e\u003cp class=\"first\"\u003eRequires Python 2.6 or above.\u003c/p\u003e\n\u003cp\u003eJinja2 (easy_installable).\u003c/p\u003e\n\u003cp class=\"last\"\u003eFor the Quixote Web UI, Quixote 2.6 (also easy_installable).\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003eClient side:\u003c/dt\u003e\n\u003cdd\u003ePython.  Should work down to Python 2.4.  Developed with 2.5.\u003c/dd\u003e\n\u003c/dl\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch1\u003e\u003ca id=\"pony-build-server\" name=\"pony-build-server\"\u003epony-build server\u003c/a\u003e\u003c/h1\u003e\n\u003cp\u003eThe command:\u003c/p\u003e\n\u003cpre class=\"literal-block\"\u003e\npython -m pony_build.web.run -f \u0026lt;shelve filename\u0026gt; -p \u0026lt;port\u0026gt;\n\u003c/pre\u003e\n\u003cp\u003ewill run the Quixote-based pony-build Web app on the given port,\nreading \u0026amp; writing from the sqlite database in 'filename'.  If you omit\nthe '-f' argument, it will use an in-memory database.\u003c/p\u003e\n\u003cp\u003eFor example,\u003c/p\u003e\n\u003cpre class=\"literal-block\"\u003e\npython -m pony_build.web.run -f test.db -p 8080\n\u003c/pre\u003e\n\u003cp\u003ewill run a server that can be accessed on \u003ca class=\"reference\" href=\"http://localhost:8080/\"\u003ehttp://localhost:8080/\u003c/a\u003e.  This\nserver will report on whatever results are sent to it by the client (see\nbelow), based on the package name ('name', below).  All data will be\nsaved to 'test.db'.\u003c/p\u003e\n\u003cp\u003eSee 'architecture, and extending pony-build', below.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch1\u003e\u003ca id=\"pony-build-client-scripts\" name=\"pony-build-client-scripts\"\u003epony-build client scripts\u003c/a\u003e\u003c/h1\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"build-scripts\" name=\"build-scripts\"\u003eBuild scripts\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eClient build scripts are just scripts that set up \u0026amp; run a list of commands:\u003c/p\u003e\n\u003cpre class=\"literal-block\"\u003e\nfrom pony_client import BuildCommand, TestCommand, do, send\n\nname = 'example'\nserver_url = 'http://localhost:8080/xmlrpc'\n\ncommands = [ BuildCommand(['/bin/echo', 'hello, world'], name='step 1'),\n             TestCommand(['/bin/echo', 'this is a test'], name='step 2')\n             ]\n\nresults = do('package', commands)\nsend('http://localhost:8080/xmlrpc', results)\n\u003c/pre\u003e\n\u003cp\u003eClient results are communicated to the server by XML-RPC, so the client\nmust be able to reach the server via the HTTP protocol.\u003c/p\u003e\n\u003cp\u003eSee \u003ctt class=\"docutils literal\"\u003e\u003cspan class=\"pre\"\u003eclient/build-cpython\u003c/span\u003e\u003c/tt\u003e for an example of building a Subversion-based\nC project (checkout, configure, make, run tests).\u003c/p\u003e\n\u003cp\u003eSee \u003ctt class=\"docutils literal\"\u003e\u003cspan class=\"pre\"\u003eclient/build-pony-build\u003c/span\u003e\u003c/tt\u003e for an example of building a Git-based\nPython project (clone, build, run tests).\u003c/p\u003e\n\u003cp\u003eNote that 'pony_client' doesn't depend on the rest of pony-build, so you\ncan distribute it with other packages if you want.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"client-query-scripts\" name=\"client-query-scripts\"\u003eClient query scripts\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eClient query scripts request information from the server.  For example,\nsee 'bin/notify-failure-email', which checks the status of the last build\nof a particular package and sends an e-mail.\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch1\u003e\u003ca id=\"architecture-and-extending-pony-build\" name=\"architecture-and-extending-pony-build\"\u003eArchitecture, and extending pony-build\u003c/a\u003e\u003c/h1\u003e\n\u003cp\u003eThe pony-build server is basically a storage receptacle for \u0026quot;bags\u0026quot; of\nkey-value pairs.  It's easiest point of extension is in the Web\ninterface, where you can substitute any WSGI app object to serve Web\npages; see 'bin/run-server', and the function call to\n'server.create(...)' (aka pony_build.server.create(...)'.\u003c/p\u003e\n\u003cp\u003eTo write a new Web UI, you will need access to the stored pony-build\nserver data.  You should work through the 'PonyBuildCoordinator'\ninterface in 'pony_build.coordinator'; you can get a handle to the\ncurrent coordinator object with 'pony_build.server.get_coordinator()'.\n\u003cstrong\u003eThe coordinator API is will be stable and public\u003c/strong\u003e, after suitable\nevolution.\u003c/p\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"client-to-server-communication\" name=\"client-to-server-communication\"\u003eClient-to-server communication\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eEach client sends two bags of information: the first, 'client_info',\ncontains information global to the build client, such as package name,\nhost name, architecture, and a list of tags.  The second,\n'results_list', is an ordered list of dictionaries, each one\nrepresenting a build step.  (The default contents of these dictionaries\nare pretty obvious: status, stderr, stdout, etc.)  Upon receipt of\nthis info, the pony-build server creates a third object, a dictionary,\ncontaining information such as the server time at which the result\nwas received,\u003c/p\u003e\n\u003cp\u003eThese three bags of info -- 'receipt', 'client_info', and\n'results_list' -- are it.  The coordinator functions give you ways to\nslice and dice which results set you want (e.g. latest for a\nparticular package), and then usually return one or more triples of\n(receipt, client_info, results_list).\u003c/p\u003e\n\u003cp\u003eClients can send arbitrary key/value pairs in their \u0026quot;bags\u0026quot;; two\nsimple ways to extend things are to add new k/v pairs for specific\npurposes, and/or to use the 'tags' key in the client_info dict.\nThe 'tags' associated value is a list of strings.\u003c/p\u003e\n\u003cp\u003ereceipt['result_key'] is the internal key used to store the result.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"notifications\" name=\"notifications\"\u003eNotifications\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eRSS2 and pubsubhubbub (\u003ca class=\"reference\" href=\"http://code.google.com/p/pubsubhubbub/\"\u003ehttp://code.google.com/p/pubsubhubbub/\u003c/a\u003e) are the\ncore of the notification system built into pony_build; the \u0026quot;officially\ncorrect\u0026quot; way to actively notify interested people of build results is\nto publish them via RSS2, push them to a pubsubhubbub server, and let\nsomeone else deal with translating those into e-mail alerts, etc.\u003c/p\u003e\n\u003cp\u003eAll of the RSS feeds that pony-build makes available can be posted to\npubsubhubbub with the proper configuration (see -P and -S options to\n\u003ctt class=\"docutils literal\"\u003e\u003cspan class=\"pre\"\u003epony_build.web.run\u003c/span\u003e\u003c/tt\u003e).  A simple example CGI callback script that\nsends an e-mail is available in\n\u003ctt class=\"docutils literal\"\u003e\u003cspan class=\"pre\"\u003eexamples/push-cgi/notifier/push-subscriber.cgi\u003c/span\u003e\u003c/tt\u003e in the pony-build\nsource distribution.\u003c/p\u003e\n\u003cp\u003eNote that there are also utility functions in \u003ctt class=\"docutils literal\"\u003e\u003cspan class=\"pre\"\u003epony_build.rss\u003c/span\u003e\u003c/tt\u003e for\nhelping to create RSS2 feeds and notify pubsubhubbub servers of\nnew results\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch1\u003e\u003ca id=\"some-medium-term-ideas\" name=\"some-medium-term-ideas\"\u003eSome medium-term ideas\u003c/a\u003e\u003c/h1\u003e\n\u003cp\u003eOne an initial release is out \u0026amp; any obvious bugs are cleaned up, here\nare some ideas for the next release.\u003c/p\u003e\n\u003cp\u003eA flexible view builder-and-saver would be nice; maybe in Django?\nThink, \u0026quot;separate results on this tag, etc; sort by time received;\nexpect these results to be shown or give an error.\u0026quot;\u003c/p\u003e\n\u003cp\u003eIt would be nice to be able to say \u0026quot;I \u003cem\u003eexpect\u003c/em\u003e a result from this\nbuildhost, where is it!?\u0026quot;\u003c/p\u003e\n\u003cp\u003eThe build client 'subprocess' calls should be able to mimic 'tee',\nthat is, give real-time output of the build.\u003c/p\u003e\n\u003cp\u003eSome form of authentication from build clients.  Josh Williams\nsuggests an approved client list (server side info about what clients\ncan conenect); I'd been thinking about a buildbot-style password setup,\nwhere build clients shared a secret with the server.  Both ideas are\ngood, I think.\u003c/p\u003e\n\u003cp\u003eIn combination with authentication, we should put a default cap on the\ntotal amount of data that can be dumped by an unauthenticated client.\nOtherwise warez sites will be hosted inside of pony-build ;)\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch1\u003e\u003ca id=\"development\" name=\"development\"\u003eDevelopment\u003c/a\u003e\u003c/h1\u003e\n\u003cp\u003epony-build is hosted on github, at: \u003ca class=\"reference\" href=\"http://github.com/ctb/pony-build\"\u003ehttp://github.com/ctb/pony-build\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eTo run the server tests:\u003c/p\u003e\n\u003cpre class=\"literal-block\"\u003e\npython -m pony_build.tests.run\n\u003c/pre\u003e\n\u003cp\u003eTo run the client tests:\u003c/p\u003e\n\u003cpre class=\"literal-block\"\u003e\ncd client\nnosetests\n\u003c/pre\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch1\u003e\u003ca id=\"design-and-ideas-for-the-future\" name=\"design-and-ideas-for-the-future\"\u003eDesign and Ideas for the Future\u003c/a\u003e\u003c/h1\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"ideas-that-are-easy-to-implement\" name=\"ideas-that-are-easy-to-implement\"\u003eIdeas that are easy to implement\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eBuild virtualenv in on the client side (as a Context?)\u003c/p\u003e\n\u003cp\u003eDependency chains example on client side.\u003c/p\u003e\n\u003cp\u003eIntegration with unittest, nose, py.test -\u0026gt; ship results back to\ncentral server.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"cleanup\" name=\"cleanup\"\u003eCleanup\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eFigure out a proper database abstraction, maybe?\u003c/p\u003e\n\u003cp\u003eTests, duh.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"things-i-don-t-know-how-to-do\" name=\"things-i-don-t-know-how-to-do\"\u003eThings I don't know how to do...\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003e...and don't want to spend time learning ;)\u003c/p\u003e\n\u003cp\u003eJosh Williams suggests supporting something other than a wsgiref\nserver.  I'm not sure this is really needed -- you can run whatever\nWSGI app you want inside the server -- but I can see that it would\nmake things more flexible for people with existing Web server setups.\nI think the way to do this is to make pony-build's (XML-RPC + WSGI\napp) interace look like its own WSGI app, rather than hacking\nSimpleXMLRPCServer and wsgiref together in an unholy union.  Ping me\nfor details if you dare.\u003c/p\u003e\n\u003cp\u003eSeriously, check out both pony_build.server.PonyBuildServer and\npony_build.server.RequestHandler (the latter is the most interesting).\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"some-general-design-principles\" name=\"some-general-design-principles\"\u003eSome general design principles\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eTitus says: A number of people are interested in pony-build, and I've\ngotten many suggestions already.  This has basically forced me to\narticulate a number of my design principles, including some that were\nmade un- or subconsciously, and/or just enshrined in my prototype\ncode.  I may change some of these decisions for v2, but I'd just as\nsoon let buildbot pick up the higher-end ideas if they're game, too.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cp class=\"first\"\u003eAll client/server interactions should be via RPC, and hence\ntransactional.  No always-on connections, no real-time control by\nthe central server.\u003c/p\u003e\n\u003cp\u003eThis is a major simplification and makes it possible to keep the\ncode base small and simple.  Yay.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cp class=\"first\"\u003eNo partial results.  Doug Phillips ('dgou') suggested that we allow\nbuild clients to \u0026quot;push\u0026quot; individual results as they happen, rather\nthan all at once at the end.  I can't think of a good, simple way\nto do that, and it's part of the 20% that I don't yet need myself.\u003c/p\u003e\n\u003cp\u003eHere's a proposal that I think would work, from Doug:\u003c/p\u003e\n\u003cpre class=\"literal-block\"\u003e\nsend \u0026quot;create new record, marked unfinished\u0026quot;\nreceive \u0026quot;record marker, update token\u0026quot;\nsend \u0026quot;first results, authenticate with update token\u0026quot;\nreceive \u0026quot;ack\u0026quot;\nsend \u0026quot;2nd results, authenticate with update token\u0026quot;\nreceive \u0026quot;ack\u0026quot;\n...\nsend \u0026quot;final results, authenticate with update token\u0026quot;\nreceive \u0026quot;ack\u0026quot;\n\u003c/pre\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"contributors\" name=\"contributors\"\u003eContributors\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eJacob Kaplan-Moss, Max Laite, Jack Carlson, Fatima Cherkaoui, and Khushboo\nShakya have all contributed code and ideas.\u003c/p\u003e\n\u003cp\u003e(If I'm missing anyone, please drop me a note!)\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"acks\" name=\"acks\"\u003eAcks\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eTitus says: Jesse Noller, Doug Philips, and Josh Williams discussed\nthings with me and are, collectively, entirely responsible for any bad\ndesign decisions; the good ones are all mine.\u003c/p\u003e\n\u003cp\u003eSeriously, I appreciate the suggestions and comments from these fine\npeople, even though Doug has been a jerk to me since then.\u003c/p\u003e\n\u003cp\u003eEric Henry built what I would consider 'pony-build prototype 1',\nproject-builder-pie.\u003c/p\u003e\n\u003cp\u003eYou can also read this discussion starting here,\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ca class=\"reference\" href=\"http://lists.idyll.org/pipermail/testing-in-python/2009-March/001277.html\"\u003ehttp://lists.idyll.org/pipermail/testing-in-python/2009-March/001277.html\u003c/a\u003e\u003c/blockquote\u003e\n\u003cp\u003ewhere Kumar suggests that I just use Hudson for chrissakes.  He's\nprobably right.\u003c/p\u003e\n\u003cp\u003eEric Holscher and Jacob Kaplan-Moss took the pony-build idea and ran\nwith it, producing a parallel universe of Django-based reporting\nservers and REST-ish clients that report via JSON.  Check out\ndevmason.com and 'pony_barn' to see their approach in action.\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"section\"\u003e\n\u003ch2\u003e\u003ca id=\"references\" name=\"references\"\u003eReferences\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003ewebhooks: \u003ca class=\"reference\" href=\"http://webhooks.pbworks.com/\"\u003ehttp://webhooks.pbworks.com/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e--\u003c/p\u003e\n\u003cp\u003eCTB 2/24/10\u003c/p\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/div\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctb%2Fpony-build","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fctb%2Fpony-build","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fctb%2Fpony-build/lists"}