Notificações de controle de versão (push)

Passamos de um sistema de controle de versão centralizado para um sistema distribuído há alguns anos. O maior obstáculo ou ponto de confusão para a equipe parecia ser a fusão .

Com a subversão , tentativas de cometer um arquivo que tinha sido modificada (e comprometida com o servidor por outro usuário) foi recebido com uma advertência sobre não ter a última revisão. Isso seria seguido por uma atualização pelo desenvolvedor e, em seguida, uma fusão . Isso é realmente o mesmo que o que é feito com o mercurial , a única diferença sendo que um commit ou atualização em um sistema distribuído é uma operação local. Um empurrão e um puxão são as operações que saem através da rede para se comunicar com outro repositório (este pode ser um designadorepositório central). Com o sistema distribuído, um desenvolvedor tem a vantagem de ser capaz de fazer commits menores e mais atômicos – um Good Habit TM. Mesclando alterações uma vez que você tinha vários commits locais faz o merge um pouco mais complicado (mas não que muito mais) – este é provavelmente o que causou algumas das dificuldades com a equipe.

Para tornar a transição mais fácil para a equipe e fazer com que o fluxo de trabalho pareça um pouco semelhante à subversão , implementamos ” notificações push ” (não o tipo popularizado por sistemas operacionais / estruturas de smartphones ). Esta é uma mensagem automática que todos na equipe recebem no cliente de memo / mensagem instantânea interno – toda vez que alguém (comete e) envia algum código. Dependendo do volume de commits e do número de projetos em execução em sua organização, você pode transmitir uma mensagem para todos ou apenas para os usuários com permissão para enviar código para um repositório específico. Essa mensagem permitia puxar e atualizar (e mesclar) mais cedo em vez de esperar até o momento em que a fusão se torne mais difícil. Se isso não interromper o fluxo de sua equipe, também pode ser um ótimo momento para os membros da equipe que trabalham em áreas relacionadas do código fornecerem um feedback rápido sobre a interoperabilidade.

[hooks]
changegroup
.notifyViaIPMsg = ...

Cenário

É daí que vem a história, agora para mais detalhes. Para criar as “notificações push”, usamos ganchos mercuriais para invocar o programa de mensagens instantâneas . Um script é configurado no gancho com o caminho para o repositório que acabou de receber um push (um changegroup ). O script então analisa o arquivo de configuração do repositório ( .hg / hgrc ) para obter a lista de usuários que têm permissão para enviar alterações no repositório ( allow_push ). Cada um desses usuários recebe uma mensagem notificando-os sobre o conjunto de alterações mais recente. Como alternativa, você pode optar por enviar uma mensagem a todos em seu grupo (mesmo aqueles que trabalham em outros projetos) – isso pode (ou não !?) ser bom do ponto de vista motivacional visão de toda a equipe – mais empurrões podem ajudar com a cultura da equipe, talvez um pouco de competição para mostrar qual equipe do projeto acabou de empurrar!

Inicialmente, começamos com um arquivo em lote simples no diretório de cada projeto (.hg / pushNotify.bat), depois mudamos para um script php comum rodando na máquina que é nosso repositório central designado – este analisa a lista allow_push .

Nossa implementação específica é fornecida a seguir como um exemplo, também usamos IPs estáticos (ou endereços mac mapeados em nosso servidor dhcp) e, portanto, podemos criar um script rápido como este. Sua equipe ou organização pode usar outro sistema de autenticação e cliente de mensagens e precisaria fazer algo diferente, mas a ideia geral é apresentada a seguir.

TestProject / .hg / hgrc

[web]
contact
= Pranav Tekchand
description
= Test Project is about more details
name
= TestProject
allow_push
= ptekchand, coderx, developery, managerz
#allow_push = *

[hooks]
# You must pass the path to the repo in quotes, especially if it contains a space. Don't add a trailing '/'
# The second parameter is the name of the repository (or project etc)
# create a IPMsgNotifyList.txt with one IP address per line for each machine you want to notify
# IPMsgNotifyList.txt not used any more common list used based on allow_push line.
changegroup
.notifyViaIPMsg = d:/repos.merc/IPMsgNotify.bat "D:\repos.merc\TestProject" "TestProject"

D: \ repos.merc \ IPMsgNotify.bat

@echo off
REM
The previous version read from a text file named IPMsgNotifyList.txt in each project's hgrc
REM This version looks up IP addresses from the usernames mentioned in the web.allow_push config

REM variable of the hgrc of the repo.. This is done from PHP.

REM See: hgPushNotify.php


REM A mercurial hook target to notify specific people of a push in a particular repository.

REM Pass the path to the repository as the first parameter to this script

REM In hgrc, under [hooks] add something like "changegroup.notifyOnIPMsg = /path/to/IPMsgNotify.bat "drive:/path/to/repo" "repoName"

REM Use back slashes as the path separator (forward slashes don'
t seem to work on server 2003. Though they work on XP SP3). Also, don't
REM Add a trailing '
\'
REM
Quick and dirty hack by (If there are any issues, get) Pranav Tekchand.

REM
Configure the path to IP Messenger on this system
set PHPPATH=x:/xampp/php/php.exe
set SCRIPTPATH=x:\xampp\htdocs\learn\tools\hgPushNotify.php

set REPOPATH=%~1
set REPONAME=%~2

if not defined REPOPATH (
echo REPOPATH
not defined.
exit /b
)
if not defined REPONAME (
echo REPONAME
not defined.
exit /b
)

REM
* X:\xampp\php\php.exe -f X:\xampp\htdocs\learn\hgPushNotify.php "D:\repos.merc\ProjectName\Platform" "ProjectName/Platform"

%PHPPATH% -f %SCRIPTPATH% "%REPOPATH%" "%REPONAME%"
REM
----------------------------------------------------------------------------------
REM your repo
/.hg/hgrc should add something like this:
REM
[hooks]
REM
# You must pass the path to the repo in quotes, especially if it contains a space. Don't add a trailing '/'
REM
# The second parameter is the name of the repository (or project etc)
REM
# create a IPMsgNotifyList.txt with one IP address per line for each machine you want to notify
REM changegroup
.notifyViaIPMsg = d:/repos.merc/IPMsgNotify.bat "D:/installers/IPMsg/testRepo" "test repo"

X: \ xampp \ htdocs \ learn \ tools \ hgPushNotify.php

<?php
/**
* The mercurial repositories hosted here call this PHP script to notify the people working on the project

* about changesets being pushed.

* Called using the hooks.changegroup hg config option

* Parameters

* - Path to repo.

* - Label/Name for repo.

*

* Usage:

* X:\xampp\php\php.exe -f X:\xampp\htdocs\learn\tools\hgPushNotify.php "D:\repos.merc\ProjectName\Platform" "ProjectName/Platform"

*/

set_time_limit
(60);

function hgPushNotify($repoPath, $repoName) {
$hgPath
= 'D:\\Program_Files\\Mercurial\hg.exe';
$ipMsgPath
= 'd:/Installers/IPMsg/ipmsg.exe';
// IP Addresses of users to send them IP messages.
// TODO: Support multiple IPs for users as well.
$baseIP
= '192.168.0.';
$userIPs
= array(
'ptekchand'=> '101',
'coderx'=> '102',
'developery'=> '103',
// ...
//''=>'',
// Not Developers
'managerz'=> '64',
);

// Resolve the repoPath's path
$repoPathOrig
= $repoPath;
$repoPath
= realpath($repoPath);
if(false===$repoPath) {
echo
"Unable to find($repoPathOrig)";
return false;
}

if(false===is_dir($repoPath)) {
echo
"Unable to switch to repo dir (".$repoPath.") - doesn't seem to be a directory.";
return false;
}
// Set the repoPath to the current working directory
chdir
($repoPath);
// repoName may be accessed from web.name
// Parse or read web.allow_push
$outputList
= null;
$hgOptions
= 'showconfig web.allow_push';
$cmd
= $hgPath.' '.$hgOptions;
$res
= execCommand($cmd, $outputList);
if(false===$res) {
echo
"Unable to run HG Command ($hgOptions)";
return false;
}
//print_r($outputList);
$notifyReceivers
= array();
if(is_array($outputList) && count($outputList)>0) {
$notifyReceivers
= explode(',', $outputList[0]);
} else {
echo
"No users listed in web.allow_push for $repoName ?";
return false;
}

$outputList
= array();
$hgOptions
= 'log -l 1';
$cmd
= $hgPath.' '.$hgOptions;
$res
= execCommand($cmd, $outputList);
if(false===$res) {
echo
"Unable to run HG Command ($hgOptions)";
return false;
}
//print_r($outputList);
$changesetDetails
= "";
if(is_array($outputList) && count($outputList)>0) {
$changesetDetails
= implode('. ', $outputList); // Would be cool if there was a way to send newlines.
} else {
echo
"Unable to fetch the log details for the last changeset in $repoName ";
$changesetDetails
= "Empty commit message! Everyone descend upon the commiter! You have explaining to do, buster.";
return false;
}
$logMessage
= "Push Notification ($repoName)".'. '.$changesetDetails;

foreach($notifyReceivers as $receiver) {
$receiver
= trim($receiver);
$rIPAddress
= isset($userIPs[$receiver]) ? $userIPs[$receiver] : false;
if($rIPAddress) {
$rIPAddress
= $baseIP.$rIPAddress;
$cmd
= $ipMsgPath.' '."/MSG $rIPAddress \"$logMessage\"""";
//echo ""Will execute:\n$cmd\n"";
$res
= execCommand($cmd