Skip to content
Snippets Groups Projects
Commit 84f6a2bc authored by hahn's avatar hahn
Browse files

- change of project config: include a php --> json in overview page

- new feature: create a new project
- help menu links to several wiki pages
parent d30eabe2
No related branches found
No related tags found
No related merge requests found
iml:$apr1$AUcEY.ns$FqqznbqFI.tPNno07nyCI0
......@@ -18,23 +18,23 @@ if (!array_key_exists("prj", $aParams)){
<h3>Steckbrief</h3>
' . $oPrj->renderProjektInfos() . '
</div>
<h3>Phasen</h3>
<h3>Phasen</h3>';
if ($oPrj->getActivePhases()) {
$sPhpOut.='
<p>
F&uuml;r das Projekt sind folgende Phasen konfiguriert:
</p>
'.$oPrj->renderPhaseInfo().'
<br>
'.$oPrj->renderLink("build").'
' . $oPrj->renderPhaseInfo() .'<br>
' . $oPrj->renderLink("build").'<br><br>
<br><br>
<h3>Build-Versionen</h3>
'.$oPrj->renderVersionUsage().'
<!--
<br>
$oPrj->getVersions()<br>
<pre>'.print_r($oPrj->getVersions(), true).'</pre>
-->
';
' . $oPrj->renderVersionUsage();
} else {
$sPhpOut.=getBox("info", "Es wurde noch keine URL in keiner der Phasen definiert").
$oPrj->renderLink("setup");
}
}
?>
......@@ -5,22 +5,30 @@ require_once("./classes/project.class.php");
require_once("./inc_functions.php");
$sOut = '';
$sOut.='<h2>Axels aktuelle Baustelle - Diese Seite noch ignorieren!!</h2>';
// --- Checks
if ($aParams["prj"] == "all") {
$sOut.='<h2>TODO: neues Projekt</h2>';
// setup a new project
$sOut.='<h2>Neues Projekt anlegen</h2>'
. '<p>
<strong>Tipp: </strong> Lass ein neues Projekt durch den Sysadmin anlegen!<br>
Das Anlegen eines Projektes hier ist nur ein Teilschritt.
für das Deployment. Server müssen durch einen Sysadmin
mit Puppet aufgesetzt sein.<br>
Weiterhin werden Zugriffsdaten auf das Repository benötigt.
</p><hr>';
$oPrj = new project();
if (array_key_exists("setupaction", $aParams) && $aParams["setupaction"] == "create") {
// TODO - FORM Daten wurden gesendet... check - create ...
$sOut.="TODO FORM Daten wurden gesendet... check - create ... <br>";
} else {
$sOut.=$oPrj->renderNewProject();
$sError = $oPrj->create($aParams["id"]);
if (!$sError) {
header("location: /deployment/" . $aParams["id"] . "/setup/");
}
$sOut.=getBox("error", $sError);
}
$sOut.=$oPrj->renderNewProject();
} else {
// setup page of a an existing project
$oPrj = new project($aParams["prj"]);
// $sOut.='<div style="float: right">aParams:<pre>'.print_r($aParams, true).'</pre></div>';
......
......@@ -172,9 +172,11 @@ class project {
// ----------------------------------------------------------------------
private function _getConfigFile($sId) {
if (!$sId) die("_getConfigFile requires an ID");
if (!$sId)
die("_getConfigFile requires an ID");
return __dir__ . '/' . $this->_sCfgdir . '/' . $sId . ".json";
}
/**
* get a full ath for temp directory (for a build)
* @return string
......@@ -184,7 +186,7 @@ class project {
}
/**
* get full path where the project builds are (a build creates a subdir)
* get full path where the project builds are (a build setes a subdir)
* @return string
*/
private function _getBuildDir() {
......@@ -221,7 +223,6 @@ class project {
if ($sPlace == "onhold")
$sBase.="_onhold";
// $sBase .= "/" . $this->_aPrjConfig["fileprefix"];
// url for deployed
if ($sPlace == "deployed") {
if ($this->isActivePhase($sPhase) && array_key_exists("url", $this->_aPrjConfig["phases"][$sPhase])) {
......@@ -286,8 +287,11 @@ class project {
// --- read all file entries
$aReturn = array();
$sDir = $this->_getProjectArchiveDir();
foreach (scandir($this->_getProjectArchiveDir()) as $sEntry){
if (is_dir($sDir.'/'.$sEntry) && $sEntry != '.' && $sEntry != '..') $aReturn[$sEntry]=false;
if (is_dir($sDir)) {
foreach (scandir($sDir) as $sEntry) {
if (is_dir($sDir . '/' . $sEntry) && $sEntry != '.' && $sEntry != '..')
$aReturn[$sEntry] = false;
}
}
$this->_aVersions = $aReturn;
......@@ -313,8 +317,7 @@ class project {
foreach (scandir($dir) as $sEntry) {
if (is_dir($dir . '/' . $sEntry) && $sEntry != '.' && $sEntry != '..') {
$this->_rmdir($dir . '/' . $sEntry);
}
elseif (is_file($dir.'/'.$sEntry) || is_link($dir.'/'.$sEntry))
} elseif (is_file($dir . '/' . $sEntry) || is_link($dir . '/' . $sEntry))
unlink($dir . '/' . $sEntry);
}
return rmdir($dir);
......@@ -366,8 +369,11 @@ class project {
$sDir = $this->_getBuildDir();
$aDirlist = array();
$aDelete = array();
if (is_dir($sDir)) {
foreach (scandir($sDir) as $sEntry) {
if (is_dir($sDir.'/'.$sEntry) && $sEntry != '.' && $sEntry != '..') $aDirlist[]=$sEntry;
if (is_dir($sDir . '/' . $sEntry) && $sEntry != '.' && $sEntry != '..')
$aDirlist[] = $sEntry;
}
}
// keep a few
......@@ -510,6 +516,24 @@ class project {
return $this->_aData["phases"][$sPhase];
}
/**
* get a list of all existing projects as a flat array
* <code>
* print_r($oPrj->getProjects());
* </code>
* returns<br>
* Array ( [0] => project1 [1] => project2 )
* @return array
*/
public function getProjects() {
$aReturn = array();
foreach (glob(__dir__ . '/' . $this->_sCfgdir . "/*.json") as $filename) {
$aReturn[] = str_replace(".json", "", basename($filename));
}
sort($aReturn);
return $aReturn;
}
/**
* check if the given phase is active for this project
* @param type $sPhase
......@@ -517,9 +541,7 @@ class project {
*/
public function isActivePhase($sPhase) {
return (
array_key_exists($sPhase, $this->_aPrjConfig["phases"])
&& array_key_exists("url", $this->_aPrjConfig["phases"][$sPhase])
&& $this->_aPrjConfig["phases"][$sPhase]["url"]
array_key_exists($sPhase, $this->_aPrjConfig["phases"]) && array_key_exists("url", $this->_aPrjConfig["phases"][$sPhase]) && $this->_aPrjConfig["phases"][$sPhase]["url"]
);
}
......@@ -530,6 +552,7 @@ class project {
public function getPhases() {
return $this->_aConfig["phases"];
}
/**
* get a flat array with active phases of the project
* @return array
......@@ -607,6 +630,7 @@ class project {
return false;
}
/**
* get current revision from remote repo
* @return string
......@@ -614,10 +638,9 @@ class project {
public function getRepoRevision($bRefresh = false) {
$sReturn = "";
if (
array_key_exists("source", $this->_aData["phases"])
&& $this->_aData["phases"]["source"]
&& $bRefresh==false
) return $this->_aData["phases"]["source"];
array_key_exists("source", $this->_aData["phases"]) && $this->_aData["phases"]["source"] && $bRefresh == false
)
return $this->_aData["phases"]["source"];
switch ($this->_aPrjConfig["build"]["type"]) {
case "git":
$sKeyfile = dirname(dirname(__file__)) . "/" . $this->_aPrjConfig["build"]["keyfile"];
......@@ -725,7 +748,6 @@ class project {
<div class="' . $sClass . '">
' . $sMessage . '
</div>';
}
/**
......@@ -753,7 +775,8 @@ class project {
$sTempDir = $this->_getTempDir();
$sFirstLevel = $this->getNextPhase();
if (!$sFirstLevel) return false;
if (!$sFirstLevel)
return false;
$sReturn.="<h3>Create a temporary build dir</h3>";
if (!file_exists($sTempDir)) {
......@@ -780,7 +803,6 @@ class project {
$sReturn.=$this->_execAndSend("export GIT_SSH=$sWrapper ; export PKEY=$sKeyfile; git clone " . $this->_aPrjConfig["build"]["ssh"] . " $sTempDir ");
// $sVersion=$this->_execAndSend("cd $sTempDir && export GIT_SSH=$sWrapper ; export PKEY=$sKeyfile; git pull " . $this->_aPrjConfig["build"]["ssh"]);
// control: directory listing after checkout
$sReturn.=$this->_execAndSend("ls -lisa $sTempDir");
......@@ -842,8 +864,6 @@ class project {
$sReturn.=$this->_execAndSend("cd $sTempDir && rm -rf .git");
// $sReturn.=$this->_execAndSend("cd $sTempDir && rm -rf .svn");
// $sReturn.=$this->_execAndSend("find $sTempDir -type d -name '.svn' -exec rm -rf {} \;");
// public_html must exist
$sReturn.="<h3>check public and public_html</h3>";
......@@ -1127,26 +1147,26 @@ class project {
return $sReturn;
}
/**
* save POSTed data as project config
* @return boolean
*/
public function saveConfig(){
if (!$_POST) return false;
if (!array_key_exists("id", $_POST)) return false;
public function saveConfig($aData = false) {
if (!$aData)
$aData = $_POST;
if (!array_key_exists("id", $aData))
return false;
// if (!array_key_exists("setupaction", $_POST)) return false;
$sId=$_POST["id"];
$aData=$_POST;
$sId = $aData["id"];
// remove unwanted items
foreach (array("setupaction", "prj", "id") as $s) {
if (array_key_exists($s, $aData)) unset ($aData[$s]);
if (array_key_exists($s, $aData))
unset($aData[$s]);
}
// echo "IST <pre>" . print_r($this->_aPrjConfig, true) . "</pre>"; echo "NEU <pre>" . print_r($aData, true) . "</pre>"; die();
// make a backup of a working config
$sCfgFile = $this->_getConfigFile($sId);
$sBakFile = $this->_getConfigFile($sId) . ".ok";
......@@ -1156,6 +1176,60 @@ class project {
$this->setProjectById($sId);
return $bReturn;
}
/**
* create a new project; it returns the error message if it fails and
* an empty string if it was successful.
* @param string $sId id
* @return string
*/
public function create($sId) {
if (!$sId) {
return "Ohne ID kann ich kein Projekt anlegen.";
}
$s = preg_replace('/[a-z\-\_0-9]*/', "", $sId);
if ($s) {
return "Die ID $sId enthaelt unerlaubte Zeichen. Erlaubt sind Kleinbuchstaben, Ziffern, Minus, Unterstrich.";
}
if ($sId == "all") {
return "ID $sId ist reserviert.";
}
if (array_search($sId, $this->getProjects()) !== false) {
return "Die ID $sId ist bereits vergeben.";
}
// reset config and create a skeleton
$this->_readConfig();
$this->_aConfig["id"] = $sId;
$this->_aPrjConfig = array(
"id" => $sId, // for saveConfig
"label" => "$sId",
"fileprefix" => "$sId",
"description" => '',
"contact" => '',
"build" => array(
"type" => "",
"ssh" => "",
"keyfile" => "",
"webaccess" => "",
),
"phases" => array(
"preview" => array(),
"stage" => array(),
"live" => array(),
),
);
$this->_verifyConfig(); // check skeleton
$bReturn = $this->saveConfig($this->_aPrjConfig);
if (!$bReturn) {
return "Das neue Projekt konnte nicht gespeichert werden.";
}
// alles OK - dann leeren String
return "";
}
// ----------------------------------------------------------------------
// RENDERING
// ----------------------------------------------------------------------
......@@ -1167,7 +1241,6 @@ class project {
* @param float $fAlpha alpha channel for rgba; 0..1
* @return string
*/
function getChecksumDiv($sText, $sFormat = "hex", $fAlpha = 1.0) {
return '<div style="background: ' . $this->getChecksumColor($sText, $sFormat, $fAlpha) . '; height: 3px;"> </div>';
}
......@@ -1211,7 +1284,7 @@ class project {
'label' => 'Accept'
),
'build' => array('icon' => 'icon-forward', 'class' => $sFirst,
'hint'=>'neues Paket erstellen und in [' .$this->getNextPhase() . '] stellen.',
'hint' => 'neues Paket erstellen und in [' . $sFirst . '] stellen.',
'label' => 'Build'
),
'cleanup' => array('icon' => 'icon-chevron-right', 'class' => ''),
......@@ -1240,8 +1313,13 @@ class project {
array_key_exists($sFunction, $aLinkdata) && array_key_exists("class", $aLinkdata[$sFunction])
) ? $aLinkdata[$sFunction]['class'] : '';
$sLink="/deployment/".$this->_aConfig["id"]."/$sFunction/";
if ($sPhase) { $sLink.="$sPhase/"; }
$sLink = "/deployment/" . $this->_aConfig["id"] . "/";
if ($sFunction != "overview") {
$sLink.="$sFunction/";
}
if ($sPhase) {
$sLink.="$sPhase/";
}
return '<a href="' . $sLink . '" title="' . $sHint . '" class="btn ' . $sClass . '"><i class="' . $sIconClass . '"></i> ' . $sLabel . '</a>';
}
......@@ -1313,10 +1391,18 @@ class project {
*/
public function renderPhaseDetail($sPhase, $sPlace, $bActions = true, $bLong = true) {
if (!$sPhase) { return false; }
if (!$sPlace) { return false; }
if (!$this->isActivePhase($sPhase)) { return false; }
if (!array_key_exists($sPlace, $this->_aPlaces )) { return false; }
if (!$sPhase) {
return false;
}
if (!$sPlace) {
return false;
}
if (!$this->isActivePhase($sPhase)) {
return false;
}
if (!array_key_exists($sPlace, $this->_aPlaces)) {
return false;
}
$sReturn = false;
$aDataPhase = $this->getPhaseInfos($sPhase);
......@@ -1350,7 +1436,9 @@ class project {
if (array_key_exists("deploytimes", $this->_aConfig[$sPhase])) {
$sReturn .= '<br><i class="icon-time"></i> Deployment:<br>' . implode("<br>", array_values($this->_aPhases[$sPhase]["deploytimes"]));
}
if ($bActions) {$sReturn .= $this->renderLink("deploy", $sPhase);}
if ($bActions) {
$sReturn .= $this->renderLink("deploy", $sPhase);
}
}
break;
......@@ -1404,7 +1492,9 @@ class project {
* @return string|boolean
*/
public function renderAllPhaseDetails($sPhase, $bActions = true, $bLong = true) {
if (!$sPhase) { return false; }
if (!$sPhase) {
return false;
}
if (!$this->isActivePhase($sPhase)) {
return '
<td class="' . $sPhase . ' tdphase ' . $this->_aConfig["id"] . '" colspan="' . count($this->_aPlaces) . '">
......@@ -1418,6 +1508,7 @@ class project {
}
return $sRow2;
}
/**
* return html code for the installed version in the repository
* @return string
......@@ -1472,9 +1563,9 @@ class project {
$bFound = false;
if (is_array($aData) && count($aData))
foreach ($aData as $i => $aPhaseUsage) {
if ($aPhaseUsage["phase"]==$sPhase
&& $aPhaseUsage["place"]==$sPlace
) $bFound=true;
if ($aPhaseUsage["phase"] == $sPhase && $aPhaseUsage["place"] == $sPlace
)
$bFound = true;
}
if ($bFound) {
$sReturn.='<td class="' . $sPhase . '" style="text-align: center;">X</td>';
......@@ -1561,7 +1652,6 @@ class project {
<div class="tab-pane active" id="tab1">
',
),
'input' . $i++ => array(
'type' => 'text',
......@@ -1641,7 +1731,6 @@ class project {
'name' => 'build[webaccess]',
'label' => 'URL zur Web GUI des Repositorys',
'value' => $this->_aPrjConfig["build"]["webaccess"],
// 'required' => 'required',
'validate' => 'isastring',
'size' => 100,
'placeholder' => '',
......@@ -1654,11 +1743,11 @@ class project {
'value' => $this->_aPrjConfig["fileprefix"],
'required' => 'required',
'validate' => 'isastring',
'pattern' => '[a-z0-9\-\_]*',
'size' => 100,
'placeholder' => '',
),
// --------------------------------------------------
'input' . $i++ => array(
'type' => 'markup',
'value' => ' </div><div class="tab-pane" id="tab3">
......@@ -1714,15 +1803,17 @@ class project {
$oForm = new formgen($aForms);
return $oForm->renderHtml("setup");
}
/**
* return html code for the setup form for a new project
* @return string
*/
public function renderNewProject() {
global $aParams;
require_once ("formgen.class.php");
$i = 0;
$sID = array_key_exists("id", $aParams) ? $aParams["id"] : "";
$aForms = array(
'setup' => array(
......@@ -1739,13 +1830,14 @@ class project {
),
'input' . $i++ => array(
'type' => 'text',
'name' => 'label',
'label' => 'ID',
'value' => $this->_aPrjConfig["label"],
'name' => 'id',
'label' => 'ID des neuen Projekts',
'value' => $sID,
'required' => 'required',
'validate' => 'isastring',
'size' => 100,
'placeholder' => 'Projekt',
'pattern' => '[a-z0-9\-\_]*',
'placeholder' => 'Projekt: Kleinbuchstaben a-z, Ziffern, Minus, Unterstrich',
),
),
),
......
......@@ -10,10 +10,6 @@ class projectlist {
// ----------------------------------------------------------------------
// CONFIG
// ----------------------------------------------------------------------
protected $_aProjects = array();
protected $_aPhases = array("preview", "stage", "live");
protected $_sCfgfile="../config/inc_projects_config.php";
// ----------------------------------------------------------------------
// constructor
// ----------------------------------------------------------------------
......@@ -23,68 +19,21 @@ class projectlist {
* @param array $aProjects array with all projects (overrides config data)
*/
public function __construct($aProjects = false) {
$this->_readConfig();
if ($aProjects) {
$this->setConfig($aProjects);
}
}
// ----------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------
/**
* read config file
* @return boolean
*/
private function _readConfig() {
$this->_aProjects = array();
require(__dir__ . '/' . $this->_sCfgfile);
$this->_aProjects = $aProjects;
$this->_aPhases = $aConfig["phases"];
$this->_verifyConfig();
return true;
}
/**
* validate config data
* @return boolean
*/
private function _verifyConfig() {
if (!count($this->_aProjects)) {
die("ERROR: no project was found.");
}
// TODO: verify
return true;
}
// ----------------------------------------------------------------------
// GETTER
// ----------------------------------------------------------------------
/**
* get list of all project IDs
* @return type
*/
public function getProjects() {
return array_keys($this->_aProjects);
}
// ----------------------------------------------------------------------
// SETTER
// ----------------------------------------------------------------------
/**
* applay a custom project array - TODO: DLETE??
* @param array $aProjects
* @return boolean
*/
public function setConfig($aProjects) {
$this->_aProjects = $aProjects;
$this->_verifyConfig();
return true;
}
// ----------------------------------------------------------------------
// ACTIONS
// ----------------------------------------------------------------------
......@@ -99,26 +48,24 @@ class projectlist {
$sTrClass="trproject";
$sColClass="tdphase";
$oPrj1 = new project();
$sPrjFilter='';
$sPhaseFilter='';
$sPrjFilter.='<option value="'.$sTrClass.'">Alle</option>';
$sPhaseFilter.='<option value="'.$sColClass.'">Alle</option>';
foreach (array_keys($this->_aPhases) as $sPhase) {
// foreach (array_keys($this->_aPhases) as $sPhase) {
foreach (array_keys($oPrj1->getPhases()) as $sPhase) {
$sPhaseFilter.='<option value="'.$sPhase.'">'.$sPhase.'</option>';
}
// loop over projects
foreach ($this->_aProjects as $sPrj => $aData) {
foreach ($oPrj1->getProjects() as $sPrj) {
$oPrj = new project($sPrj);
$sPrjFilter.='<option value="'.$sPrj.'">'.$oPrj->getLabel().'</option>';
// $aPrjData = $oPrj->getAllPhaseInfos();
$sOutPhases = '';
// loop over phases ...
foreach (array_keys($this->_aPhases) as $sPhase) {
foreach (array_keys($oPrj->getPhases()) as $sPhase) {
$sOutPhases.=$oPrj->renderAllPhaseDetails($sPhase,true,false);
}
......@@ -133,7 +80,6 @@ class projectlist {
' . $oPrj->getDescription() . '</td><td class="prj">';
if ($oPrj->canAcceptPhase()){
$sNext=$oPrj->getNextPhase();
$sOut.=$oPrj->renderLink("build");
// $sOut.='<a href="/deployment/'.$sPrj.'/build/" class="btn '.$sNext.'"><i class=" icon-forward"></i> Build f&uuml;r ['.$sNext.']</a><br>';
}
......@@ -141,7 +87,7 @@ class projectlist {
' . $sOutPhases . '
</tr>';
}
if ($sOut)
if ($sOut) {
$sRowHead1='';
$sRowHead2='';
......@@ -183,7 +129,7 @@ class projectlist {
</thead>
<tbody>
' . $sOut . '</tbody></table>';
}
return $sOut;
}
......
......@@ -85,6 +85,7 @@ function getTopArea(){
*
*/
$sBaseUrl='/deployment/';
$sWikiBaseUrl='https://secure.iml.unibe.ch/wiki/doku.php';
$sReturn='
<div class="navbar">
<div class="navbar-inner">
......@@ -98,11 +99,14 @@ function getTopArea(){
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Projekte<b class="caret"></b></a>
<ul class="dropdown-menu">
';
foreach ($oPrjList->getProjects() as $sPrj){
$oPrj1 = new project();
foreach ($oPrj1->getProjects() as $sPrj){
$oPrj = new project($sPrj);
$sReturn.='<li><a href="'.$sBaseUrl.$sPrj.'/">'.$oPrj->getLabel().'</a></li>';
}
$sReturn.='
<li class="divider"></li>
<li><a href="'.$sBaseUrl.'all/setup/">Neues Projekt</a></li>
</ul>
</li>';
if (array_key_exists("prj", $aParams) && $aParams["prj"]<>"all"){
......@@ -145,7 +149,15 @@ function getTopArea(){
-->
</ul>
<ul class="nav pull-right">
<li><a href="https://secure.iml.unibe.ch/wiki/doku.php/it/entwicklung/continuous_deployment"><i class=" icon-question-sign"></i> Hilfe</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class=" icon-question-sign"></i> Hilfe<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="'.$sWikiBaseUrl.'/it/entwicklung/continuous_deployment">WIKI: Übersicht Continous Deployment</a></li>
<li><a href="'.$sWikiBaseUrl.'/it/entwicklung/continuous_deployment#konventionen">WIKI: Konventionen für Entwickler</a></li>
<li><a href="'.$sWikiBaseUrl.'/it/infrastruktur/dienste/puppet/snippets#iml-deployment">WIKI (Admin): Puppet-Snippets für den Sysadmin</a></li>
<li><a href="'.$sWikiBaseUrl.'/it/infrastruktur/dienste/imldeployment">WIKI (Admin): Verzeichnisse und Dateien</a></li>
</ul>
</li>
</ul>
</div>
</div><div id="header2">';
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment