To be successful online, it’s no longer good enough just to have a web presence. Competition between companies means that the bar has been raised when it comes to website design. Today’s leading sites do more than simply look good, they are functional, optimised and interactive places that engage readers from the get-go. If you …
Development
ConFoo: THE web development conference you don’t want to miss!
A Web based system to push your SVN code through development, staging and production environments
Note the files in this post are now on GitHub
Hello there!
In development, having a seamlessly integrated process where you can propagate your code through whatever QA, testing and development policy you have is invaluable and a definite time saver.
We work with SVN as well as GIT code repository systems and have developed a web based system to “Export” or “Push” the code through development, staging and production environments as such.
I have already talked about sanitizing your code during the commit process, to ensure commit messages are standard and there are no PHP fatal errors, so now I will be showcasing you a simple web based system for propagating your code through development, staging and production servers.
This system should be on a secure web accessible page on each server. For the sake of argument , I’ll call each server the following :
dev.server.com — development server
staging.server.com — staging server
www.server.com — production server
We will be using PHP for the web based interface, and we will assume that you will be password protecting access to this page via htpasswd, as well as forcing SSL. I am also assuming that within your SVN repository, you have multiple “sites” that you will be individually pushing or exporting (svn export). Once you have the secure, password protected page (lets call it https://dev.server.com/svn) , the following PHP page will be the main index :
svnupdate.php
<? $ sites[] = array( "name" => "Site A", "url" => "http://site-a.server.com", "path" => "/usr/local/www/site-a.server.com", "source" => "svn://svn.server.com/repository/branches/site-a", "login" => "svnlogin", "base" => "1.00", "notes" => "Standard build for Site A" ); "name" => "Site B", "url" => "http://site-b.server.com", "path" => "/usr/local/www/site-b.server.com", "source" => "svn://svn.server.com/repository/branches/site-b", "login" => "svnlogin", "base" => "1.00", "notes" => "Standard build for Site B" ); ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>SVN Update Page</title> <style> body { background-color:#eeeeee; } .tdheader { background-color:#0f2c66; color:#FFFFFF; font-weight: bold; } .tdheader2 { background-color:#000000; color:#FFFFFF; font-weight: bold; } .tdrow { background-color:#ffffff; color:#000000; font-weight: normal; } a:link,a:active,a:visited { color:#0f2c66; } a:hover { color:#6A9CD3; } .menuon { background-color:#6699cc; color:white; font-weight: bold; } .menuoff { background-color:white; color:black; font-weight: bold; } table { border-style: solid; border-width: 1px; border-color: #000000; } </style> <script type="text/javascript"> function confirmexport(text) { if (confirm(text)) { document.getElementById('framecont').style.display = ''; document.getElementById("processframe").contentWindow.document.body.innerHTML = "<div align='center'>Exporting...</div>"; return true; } else return false; } function viewframe() { document.getElementById('framecont').style.display = ''; } function closeframe() { document.getElementById('framecont').style.display = 'none'; } </script> </head> <body> <table width="750px" cellpadding="2" cellspacing="1" bgcolor="#000000" border="0"> <tr> <td class="tdheader2">Server: </td> <td class="menuon" align="center">Development Server</td> <td class="menuoff" align="center"><a href="https://staging.server.com/svn/svnupdate.php">Staging Server</a></td> <td class="menuoff" align="center"><a href="https://www.server.com/svn/svnupdate.php">Production Server</a></td> </tr> </table> <hr size="1" noshade="noshade" /> <a href="log.php" target="processframe" onclick="closeframe();viewframe()">View Development Export Log</a> <br><br> <table cellpadding="2" width="1000px" cellspacing="1" bgcolor="#000000" border="0"> <tr class="tdheader"> <td>Site</td> <td>Source</td> <td>UN/PW</td> <td>Base</td> <td>Revision</td> <td>Export</td> <td>Pending Updates</td> <td>Notes</td> </tr> <? if($ sites) { foreach($ sites as $ key => $ value) { ?> <form method="post" action="svnupdate_process.php" target="processframe"> <tr class="tdrow"> <td><a href="<?=$ value['url']?>" target="_blank"><?=$ value['name']?></a></td> <td><?=preg_replace("/svn://svn.server.com//","",$ value['source'])?><input type="hidden" name="source" value="<?=$ value['source']?>"></td> <td><?=$ value['login']?></td> <td><?=$ value['base']?></td> <td><input type="text" name="revision" size="5"></td> <td><input type="hidden" name="site" value="<?=$ value['path']?>"> <input type="submit" name="submitbutton" value="Export" onClick="javascript:return confirmexport('This will overwrite the current files on development. Are you sure?');"> </td> <td width="150px"><center><a href="viewcommit.php?name=<?=$ value['name']?>&path=<?=$ value['path']?>&svn=<?=$ value['source']?>" target="processframe" onclick="closeframe();viewframe()">View</a></center></td> <td><?=$ value['notes']?></td> </tr> </form> <? } ?> <? } ?> </table> <br><div id='framecont' style="text-align: left; display: none"> <iframe name="processframe" id="processframe" width="1000px" height="300px" align="left" scrolling="yes" frameborder="0"> </iframe> </div> </body> </html>
If you carefully look at the above code, you will see that this page will be dependent on 3 external scripts, which I will describe below. The page itself generates a list of whatever sites you want to include in the push process, within a PHP based Array. The array details important info per site such as the name, svn location, location of the files on the server as well as whatever other notes and additional info you want to provide.
Each time a site is “exported” by clicking the export button, it calls an external script called svnupdate_process.php. This executes the SVN EXPORT command, as well as logging which user requested the action into a simple text based log file. The user is determined by the authentication user that is accessing the page. The htpassword credentials you will be providing to your users should be set per-user so that it can be easier to determine who pushed the code and whatnot.
The other two external scripts are one that will view the log file in an iframe on the same page, as well as a script to extrapolate the pending commits that are in the queue since the LAST code push / svn export. That is really useful, as you can imagine.
Script to view the export log
This script, log.php is used to dump the contents of the log.txt export log file. Very simple
log.php
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Untitled</title> </head> <body> <b>Development Export Log:</b><hr> <? include("./functions.inc.php"); $ logfile = new logfile(); $ logfile->display(); ?> </body> </html>
Simple, right? The log.php code includes a functions.inc.php file, used for writing and reading the log.txt file. The above code depends on it, as well as the svnupdate_process.php code (described below), in order to log each time someone hits the export code button
functions.inc.php
<? class logfile { function logfile() { $ this->filename = "log.txt"; $ this->Username = $ _SERVER['PHP_AUTH_USER']; $ this->logfile = $ this->filename; } function write($ data) { // write to logfile $ handle = fopen($ this->logfile, "a+"); $ date = date("Y-m-d H:i:s"); $ IP = getenv('REMOTE_ADDR'); $ data = "[$ date] {$ this->Username}:{$ IP} - " . $ data . "n"; $ return = fwrite($ handle, $ data); fclose($ handle); } function display() { // display logfile $ handle = fopen($ this->logfile, "a+"); while(!feof($ handle)) { // Pull lines into array $ lines[] = fgets($ handle, 1024); } $ count = count($ lines); $ count = $ count - 2; for($ i=$ count;$ i>=0;$ i--) { echo $ lines[$ i] . "<br>"; } fclose($ handle); } } ?>
The code of the svn export process is handled by the following script below. Again its self explanatory. PHP executes a shell command to export the svn code based on the array variables defined in the very first script. Make sure all the variables match up to whats in svn and the location of the files, and even execute a test run of the command manually with the variables. If there are problems, you can modify the command to pipe the output to a log file for further analysis. Additionally you may need to alter the permissions of the apache user so that the command can be properly run. Avoid setting the apache user to have a shell (big no-no) ,but maybe a nologin shell or something along those lines. Its completely up to you , but be very careful about the choices you make to get it to run properly.
svnupdate_process.php
<b>Update/Status Window</b> <hr> <? include("./functions.inc.php"); $ logfile = new logfile(); if($ _POST['submitbutton']) { if($ _POST['revision'] != "") { $ revision = "-r ".$ _POST['revision']; } $ command = "/usr/bin/svn export --force --username svnuser --password 'svnpassword' $ revision --config-dir /tmp ".$ _POST['source']. " " . $ _POST['site']." 2>&1"; if($ _POST['submitbutton'] == "Export") { $ output = shell_exec("umask 022;".$ command); } echo "<pre>output
”;
$ logtext = “Exported to {$ _POST[‘site’]}”;
$ logfile->write($ logtext);
eaccelerator_clear();
}
?>
Finally the last script will be the script that parses the SVN log output with a date/time range from the last time the export button was pushed, until the current date and time. This will load the output in the same iframe log window on the svn page so the user can see what pending commits are in the code since the last time it was exported. Invaluable information, right?
Note that this has a function to filter out additional illegal characters to avoid cross site scripting injections. This code should be completely 100% restricted from outside public use, however it might be worth it to put this function in the svnupdate_process.php script as well. Can’t be too careful. I thought I’d include it here for you to use.
viewcommit.php
<? if(($ _GET['svn'] != "") && ($ _GET['path'] != "") && ($ _GET['name'] != "")) { // Cross Site Script & Code Injection Sanitization function xss_cleaner($ input_str) { $ return_str = str_replace( array('<',';','|','&','>',"'",'"',')','('), array('<',':','|','&','>',''','"',')','('), $ input_str ); $ return_str = str_ireplace( '%3Cscript', '', $ return_str ); return $ return_str; } $ xss_path=xss_cleaner($ _GET['path']); $ xss_svn=xss_cleaner($ _GET['svn']); $ xss_name=xss_cleaner($ _GET['name']); echo "<b>Viewing Pending Updates For : ". $ xss_name . "</b>"; echo "<hr>"; $ command = "/usr/bin/svn --username svnuser --password 'svnpassword' --config-dir /tmp log " . $ xss_svn . " -r {"`grep "" . $ xss_path . "" log.txt | tail -n 1 | awk -F " " '{printf "%s %s", $ 1,$ 2}' | sed -e 's/[//g' -e 's/]//g'`"}:{"`date "+%Y-%m-%d %H:%M:%S"`"}"; $ output = shell_exec("umask 022;".$ command); echo "<pre>output
”;
}
else {
echo “No queries passed!”;
}
?>
Lets break down the SVN log command, so you know whats going on. I’m grabbing the SVN site array variables when the “view log” link is clicked on the svn page. I am also parsing the export log text file to get the last entry for the particular site in question, grabbing the date and time.
I am then getting the current date and time to complete the date/time range in the svn log query. The finished query should look something like this :
svn --username svnuser --password 'svnpassword' --config-dir /tmp log svn://svn.server.com -r {"2013-01-01 12:01:00"}:{"2013-02-01 12:01:00"}
Note the files in this post are now on GitHub
The post A Web based system to push your SVN code through development, staging and production environments appeared first on Managed WordPress Hosting | Managed VPS Hosting | Stack Star.
Managed WordPress Hosting | Managed VPS Hosting | Stack Star
Affordable WordPress Development in Indore – Parkhya Solutions
Parkhya Solutions Pvt. Ltd. is a well-established Web and IT Solutions company. Our experience and expertise enable us to be an excellent Web and IT training provider wordpress development in indore, Software development in Indore, Major project training in Indore. http://www.parkhya.com/
Find Articles, Free Articles Directory | Web Hosting Articles
Must Have Qualities of A Developer for E-Commerce Development
E-commerce development is a key component in making certain that you reap the benefits of modern online dealings by promoting your company on the internet via your website. To find the most from e-commerce development, you will have to take into account excellent e-commerce developers to nurture the project.
Find Articles, Free Articles Directory | Web Hosting Articles
The Significance of Web Database Development
With the huge increase of shopping online that has become open to buyers, business people have to be able to get the data on their merchandise out to the most consumers, in the most effective and superior way. A great web database developer brings these attributes to your web marketing plan and your physical stores, pulling customers directly to you because they search the exact info found on the Web.
Find Articles, Free Articles Directory | Web Hosting Articles