Added comments

This commit is contained in:
2026-04-17 11:09:46 +02:00
parent f3f4d30071
commit 39d5344d82
11 changed files with 272 additions and 99 deletions

View File

@@ -1,55 +1,82 @@
// You need a valid credentials for Docker Hub
// You need https://plugins.jenkins.io/docker-workflow/ on your jenkins instance
// Necessites credencials vàlides per a Docker Hub
// Necessites https://plugins.jenkins.io/docker-workflow/ instal·lat a la teva instància Jenkins
pipeline {
// Defineix l'agent on s'executarà el pipeline
agent {
node {
label 'docker' //Agent needs to have Docker Engine installed
label 'docker' // L'agent ha de tenir Docker Engine instal·lat
}
}
// Defineix variables d'entorn disponibles per a tot el pipeline
environment {
// Usuari de Docker Hub
DOCKER_HUB_USER='guillemhs'
// Nom de la imatge Docker amb format: usuari/nom-imatge
IMAGE_NAME="${DOCKER_HUB_USER}/jenkins-alpine-agent"
// ID de les credencials de Docker Hub guardades a Jenkins
REGISTRY_CRED_ID='docker-credentials'
// Executem una comanda shell per obtenir la data actual i la guardem com a variable
// Executem una comanda shell per obtenir la data actual (format YYYY.MM.DD)
// returnStdout: true retorna l'output de la comanda
// trim() elimina espais en blanc
DATA = sh(returnStdout: true, script: 'date +%Y.%m.%d').trim()
// Crea un tag combinant la data i el número de build (ex: 2026.04.17.5)
TAG="${DATA}.${env.BUILD_NUMBER}"
}
// Defineix les etapes principals del pipeline
stages {
// Etapa 1: Descarrega el codi del repositori
stage('Checkout') {
steps {
// Get some code from a GIT repository
// Clona el codi del repositori Git
checkout scm
}
}
// Etapa 2: Construeix la imatge Docker
stage('Docker Build') {
steps {
script{
echo "Build image ..."
// Construeix la imatge Docker usant el Dockerfile especificat
// -f DockerfileAgentAlpine: Especifica el Dockerfile per a Alpine
// .: Usa el directori actual com a context de construcció
docker.build("${IMAGE_NAME}:${TAG}","-f DockerfileAgentAlpine .")
}
}
}
// Etapa 3: Publica la imatge a Docker Hub
stage('Docker Push')
{
steps{
script{
// Autenticació amb Docker Hub usant les credencials guardades
docker.withRegistry('',REGISTRY_CRED_ID){
// Obté la referència de la imatge construïda
def app = docker.image("${IMAGE_NAME}:${TAG}")
echo "Pushing image to Docker Hub ..."
// Publica la imatge amb el tag de data i build number
app.push("${TAG}")
// Publica la imatge amb el tag 'latest' (versió més recent)
app.push("latest")
}
}
}
}
}
// Accions a executar sempre al final del pipeline
post{
always{
//cleanWs()
// cleanWs() comentat: Podria limpiar l'espai de treball si es descomentar
// Elimina la imatge Docker local amb el tag específic (|| true ignora errors)
sh "docker rmi ${IMAGE_NAME}:${TAG} || true"
// Elimina la imatge Docker local amb el tag 'latest'
sh "docker rmi ${IMAGE_NAME}:latest || true"
}
}

View File

@@ -1,55 +1,82 @@
// You need a valid credentials for Docker Hub
// You need https://plugins.jenkins.io/docker-workflow/ on your jenkins instance
// Necessites credencials vàlides per a Docker Hub
// Necessites https://plugins.jenkins.io/docker-workflow/ instal·lat a la teva instància Jenkins
pipeline {
// Defineix l'agent on s'executarà el pipeline
agent {
node {
label 'docker' //Agent needs to have Docker Engine installed
label 'docker' // L'agent ha de tenir Docker Engine instal·lat
}
}
// Defineix variables d'entorn disponibles per a tot el pipeline
environment {
// Usuari de Docker Hub
DOCKER_HUB_USER='guillemhs'
// Nom de la imatge Docker amb format: usuari/nom-imatge
IMAGE_NAME="${DOCKER_HUB_USER}/jenkins-debian-13-agent"
// ID de les credencials de Docker Hub guardades a Jenkins
REGISTRY_CRED_ID='docker-credentials'
// Executem una comanda shell per obtenir la data actual i la guardem com a variable
// Executem una comanda shell per obtenir la data actual (format YYYY.MM.DD)
// returnStdout: true retorna l'output de la comanda
// trim() elimina espais en blanc
DATA = sh(returnStdout: true, script: 'date +%Y.%m.%d').trim()
// Crea un tag combinant la data i el número de build (ex: 2026.04.17.5)
TAG="${DATA}.${env.BUILD_NUMBER}"
}
// Defineix les etapes principals del pipeline
stages {
// Etapa 1: Descarrega el codi del repositori
stage('Checkout') {
steps {
// Get some code from a GIT repository
// Clona el codi del repositori Git
checkout scm
}
}
// Etapa 2: Construeix la imatge Docker
stage('Docker Build') {
steps {
script{
echo "Build image ..."
// Construeix la imatge Docker usant el Dockerfile especificat
// -f DockerfileAgentDebian: Especifica el Dockerfile per a Debian
// .: Usa el directori actual com a context de construcció
docker.build("${IMAGE_NAME}:${TAG}","-f DockerfileAgentDebian .")
}
}
}
// Etapa 3: Publica la imatge a Docker Hub
stage('Docker Push')
{
steps{
script{
// Autenticació amb Docker Hub usant les credencials guardades
docker.withRegistry('',REGISTRY_CRED_ID){
// Obté la referència de la imatge construïda
def app = docker.image("${IMAGE_NAME}:${TAG}")
echo "Pushing image to Docker Hub ..."
// Publica la imatge amb el tag de data i build number
app.push("${TAG}")
// Publica la imatge amb el tag 'latest' (versió més recent)
app.push("latest")
}
}
}
}
}
// Accions a executar sempre al final del pipeline
post{
always{
//cleanWs()
// cleanWs() comentat: Podria limpiar l'espai de treball si es descomentar
// Elimina la imatge Docker local amb el tag específic (|| true ignora errors)
sh "docker rmi ${IMAGE_NAME}:${TAG} || true"
// Elimina la imatge Docker local amb el tag 'latest'
sh "docker rmi ${IMAGE_NAME}:latest || true"
}
}

View File

@@ -1,56 +1,83 @@
// You need a valid credentials for Docker Hub
// You need https://plugins.jenkins.io/docker-workflow/ on your jenkins instance
// Necessites credencials vàlides per a Docker Hub
// Necessites https://plugins.jenkins.io/docker-workflow/ instal·lat a la teva instància Jenkins
pipeline {
// Defineix l'agent on s'executarà el pipeline
agent {
node {
label 'docker' //Agent needs to have Docker Engine installed
label 'docker' // L'agent ha de tenir Docker Engine instal·lat
}
}
// Defineix variables d'entorn disponibles per a tot el pipeline
environment {
// Usuari de Docker Hub
DOCKER_HUB_USER='guillemhs'
IMAGE_NAME="${DOCKER_HUB_USER}/jenkins-ubuntu2404-agent"
// Nom de la imatge Docker amb format: usuari/nom-imatge
IMAGE_NAME="${DOCKER_HUB_USER}/jenkins-ubuntu-agent"
// ID de les credencials de Docker Hub guardades a Jenkins
REGISTRY_CRED_ID='docker-credentials'
// Executem una comanda shell per obtenir la data actual i la guardem com a variable
// Executem una comanda shell per obtenir la data actual (format YYYY.MM.DD)
// returnStdout: true retorna l'output de la comanda
// trim() elimina espais en blanc
DATA = sh(returnStdout: true, script: 'date +%Y.%m.%d').trim()
// Crea un tag combinant la data i el número de build (ex: 2026.04.17.5)
TAG="${DATA}.${env.BUILD_NUMBER}"
}
// Defineix les etapes principals del pipeline
stages {
// Etapa 1: Descarrega el codi del repositori
stage('Checkout') {
steps {
// Get some code from a GIT repository
// Clona el codi del repositori Git
checkout scm
}
}
// Etapa 2: Construeix la imatge Docker
stage('Docker Build') {
steps {
script{
echo "Build image ..."
// Construeix la imatge Docker usant el Dockerfile especificat
// -f DockerfileAgent2404: Especifica quin Dockerfile usar
// .: Usa el directori actual com a context de construcció
docker.build("${IMAGE_NAME}:${TAG}","-f DockerfileAgent2404 .")
}
}
}
// Etapa 3: Publica la imatge a Docker Hub
stage('Docker Push')
{
steps{
script{
// Autenticació amb Docker Hub usant les credencials guardades
docker.withRegistry('',REGISTRY_CRED_ID){
// Obté la referència de la imatge construïda
def app = docker.image("${IMAGE_NAME}:${TAG}")
echo "Pushing image to Docker Hub ..."
// Publica la imatge amb el tag de data i build number
app.push("${TAG}")
// Publica la imatge amb el tag 'latest' (versió més recent)
app.push("latest")
}
}
}
}
}
// Accions a executar sempre al final del pipeline
post{
always{
//cleanWs()
// Elimina la imatge Docker local amb el tag específic (|| true ignora errors)
sh "docker rmi ${IMAGE_NAME}:${TAG} || true"
// Elimina la imatge Docker local amb el tag 'latest'
sh "docker rmi ${IMAGE_NAME}:latest || true"
// cleanWs() comentat: Podria limpiar l'espai de treball si es descomentar
}
}
}

View File

@@ -1,8 +0,0 @@
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y git openssh-server openjdk-21-jdk
RUN mkdir /var/run/sshd
RUN useradd -m -d /home/jenkins -s /bin/bash jenkins && echo "jenkins:jenkins" | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]

View File

@@ -1,7 +1,28 @@
FROM alpine:latest
# Utilitza Alpine Linux com a imatge base (imatge molt lleugera)
FROM alpine:3.23.4
# Actualitza els repositoris de paquets i instal·la les eines necessàries:
# - git: Sistema de control de versions
# - openssh: Servidor SSH per a connexions remotes
# - openjdk21: Java Development Kit versió 21
# - bash: Shell interactiu (Alpine usa sh per defecte)
# --no-cache: No emmagatzema els paquets per reduir la mida de la imatge
RUN apk update && apk add --no-cache git openssh openjdk21 bash
# Genera les claus SSH del servidor (RSA, DSA, ECDSA, ED25519)
RUN ssh-keygen -A
# Crea l'usuari 'jenkins' amb:
# -D: Usuari del sistema (sense contrasenya de login)
# -h /home/jenkins: Estableix la carpeta home
# -s /bin/bash: Estableix bash com a shell per defecte
RUN adduser -D -h /home/jenkins -s /bin/bash jenkins
# Estableix la contrasenya 'jenkins' per a l'usuari jenkins
RUN echo "jenkins:jenkins" | chpasswd
# Exposa el port 22 (SSH) per a connexions remotes
EXPOSE 22
# Comando per iniciar el servidor SSH en mode detached (-D)
CMD ["/usr/sbin/sshd","-D"]

View File

@@ -1,6 +1,24 @@
# Utilitza Debian 13.4 slim com a imatge base (versió compacta de Debian)
FROM debian:13.4-slim
# Estableix la variable d'entorn per evitar prompts interactius durant la instal·lació de paquets
ENV DEBIAN_FRONTEND=noninteractive
# Actualitza els repositoris de paquets i instal·la les eines necessàries:
# - git: Sistema de control de versions
# - openssh-server: Servidor SSH per a connexions remotes
# - openjdk-21-jdk: Java Development Kit versió 21
RUN apt-get update && apt-get install -y git openssh-server openjdk-21-jdk
# Crea l'usuari 'jenkins' amb:
# -m: Crea la carpeta home
# -d /home/jenkins: Especifica la carpeta home
# -s /bin/bash: Estableix bash com a shell per defecte
# Estableix la contrasenya 'jenkins' per a l'usuari jenkins
RUN useradd -m -d /home/jenkins -s /bin/bash jenkins && echo "jenkins:jenkins" | chpasswd
# Exposa el port 22 (SSH) per a connexions remotes
EXPOSE 22
# Comando per iniciar el servidor SSH en mode detached (-D)
CMD ["/usr/sbin/sshd","-D"]

27
DockerfileAgentUbuntu Normal file
View File

@@ -0,0 +1,27 @@
# Utilitza Ubuntu 26.04 com a imatge base
FROM ubuntu:26.04
# Estableix la variable d'entorn per evitar prompts interactius durant la instal·lació de paquets
ENV DEBIAN_FRONTEND=noninteractive
# Actualitza els repositoris de paquets i instal·la les eines necessàries:
# - git: Sistema de control de versions
# - openssh-server: Servidor SSH per a connexions remotes
# - openjdk-21-jdk: Java Development Kit versió 21
RUN apt-get update && apt-get install -y git openssh-server openjdk-21-jdk
# Crea el directori necessari per al servent SSH
RUN mkdir /var/run/sshd
# Crea l'usuari 'jenkins' amb:
# -m: Crea la carpeta home
# -d /home/jenkins: Especifica la carpeta home
# -s /bin/bash: Estableix bash com a shell per defecte
# Estableix la contrasenya 'jenkins' per a l'usuari jenkins
RUN useradd -m -d /home/jenkins -s /bin/bash jenkins && echo "jenkins:jenkins" | chpasswd
# Exposa el port 22 (SSH) per a connexions remotes
EXPOSE 22
# Comando per iniciar el servidor SSH en mode detached (-D)
CMD ["/usr/sbin/sshd","-D"]

View File

@@ -1,31 +1,43 @@
// Defineix la configuració bàsica del pipeline
pipeline {
// Especifica que s'executarà en un agent amb l'etiqueta 'docker-alpine-agent'
agent {label 'docker-alpine-agent'}
// Defineix les eines que es descargaran i es posaran disponibles al PATH
tools {
// Install the Maven version configured as "M3" and add it to the path.
// Instal·la la versió de Maven configurada com "M3" i l'afegeix al path
maven "M3"
}
// Defineix les etapes principals del pipeline
stages {
// Etapa 1: Descarrega el codi del repositori
stage('Checkout') {
steps {
// Get some code from a GitHub repository
// Clona el repositori de GitHub amb el codi del projecte
git 'https://github.com/jglick/simple-maven-project-with-tests.git'
}
}
// Etapa 2: Construeix el projecte Maven
stage('Build'){
steps {
// Run Maven on a Unix agent.
// Executa Maven en l'agent Unix:
// -Dmaven.test.failure.ignore=true: Continua even si hi ha errors en els tests
// clean: Neteja els artifacts anteriors
// package: Compila i empaquetar el projecte
sh "mvn -Dmaven.test.failure.ignore=true clean package"
}
}
}
// Accions a executar després de completar el pipeline
post {
// If Maven was able to run the tests, even if some of the test
// failed, record the test results and archive the jar file.
// S'executa si el build ha acabat correctament
success {
// Genera un informe amb els resultats dels tests JUnit
junit '**/target/surefire-reports/TEST-*.xml'
// Emmagatzema el fitxer JAR generat com a artifact del build
archiveArtifacts 'target/*.jar'
}
}

View File

@@ -1,33 +1,44 @@
// Defineix la configuració bàsica del pipeline
pipeline {
// Especifica que s'executarà en un agent amb l'etiqueta 'docker-debian-agent'
agent {label 'docker-debian-agent'}
// Defineix les eines que es descargaran i es posaran disponibles al PATH
tools {
// Install the Maven version configured as "M3" and add it to the path.
// Instal·la la versió de Maven configurada com "M3" i l'afegeix al path
maven "M3"
}
// Defineix les etapes principals del pipeline
stages {
// Etapa 1: Descarrega el codi del repositori
stage('Checkout') {
steps {
// Get some code from a GitHub repository
// Clona el repositori de GitHub amb el codi del projecte
git 'https://github.com/jglick/simple-maven-project-with-tests.git'
}
}
// Etapa 2: Construeix el projecte Maven
stage('Build'){
steps {
// Run Maven on a Unix agent.
// Executa Maven en l'agent Unix:
// -Dmaven.test.failure.ignore=true: Continua even si hi ha errors en els tests
// clean: Neteja els artifacts anteriors
// package: Compila i empaquetar el projecte
sh "mvn -Dmaven.test.failure.ignore=true clean package"
}
}
}
// Accions a executar després de completar el pipeline
post {
// If Maven was able to run the tests, even if some of the test
// failed, record the test results and archive the jar file.
// S'executa si el build ha acabat correctament
success {
// Genera un informe amb els resultats dels tests JUnit
junit '**/target/surefire-reports/TEST-*.xml'
// Emmagatzema el fitxer JAR generat com a artifact del build
archiveArtifacts 'target/*.jar'
}
}
}

View File

@@ -1,31 +1,43 @@
// Defineix la configuració bàsica del pipeline
pipeline {
// Especifica que s'executarà en un agent amb l'etiqueta 'docker-ubuntu-agent'
agent {label 'docker-ubuntu-agent'}
// Defineix les eines que es descargaran i es posaran disponibles al PATH
tools {
// Install the Maven version configured as "M3" and add it to the path.
// Instal·la la versió de Maven configurada com "M3" i l'afegeix al path
maven "M3"
}
// Defineix les etapes principals del pipeline
stages {
// Etapa 1: Descarrega el codi del repositori
stage('Checkout') {
steps {
// Get some code from a GitHub repository
// Clona el repositori de GitHub amb el codi del projecte
git 'https://github.com/jglick/simple-maven-project-with-tests.git'
}
}
// Etapa 2: Construeix el projecte Maven
stage('Build'){
steps {
// Run Maven on a Unix agent.
// Executa Maven en l'agent Unix:
// -Dmaven.test.failure.ignore=true: Continua even si hi ha errors en els tests
// clean: Neteja els artifacts anteriors
// package: Compila i empaquetar el projecte
sh "mvn -Dmaven.test.failure.ignore=true clean package"
}
}
}
// Accions a executar després de completar el pipeline
post {
// If Maven was able to run the tests, even if some of the test
// failed, record the test results and archive the jar file.
// S'executa si el build ha acabat correctament
success {
// Genera un informe amb els resultats dels tests JUnit
junit '**/target/surefire-reports/TEST-*.xml'
// Emmagatzema el fitxer JAR generat com a artifact del build
archiveArtifacts 'target/*.jar'
}
}

View File

@@ -1,76 +1,75 @@
[![Agile611](https://www.agile611.com/wp-content/uploads/2020/09/cropped-logo-header.png)](http://www.agile611.com/)
# Agile611 Jenkins CI/CD Training
# Formació Jenkins CI/CD d'Agile611
Este repositorio ofrece scripts y una configuración mínima para levantar un entorno de Jenkins de prueba local usando Vagrant.
Aquest repositori ofereix scripts i una configuració mínima per aixecar un entorn de Jenkins de prova local usant Vagrant.
**Objetivo:** Proporcionar un punto de partida sencillo para probar Jenkins (y opcionalmente SonarQube) en entornos locales y educativos de CI.
**Objectiu:** Proporcionar un punt de partida senzill per provar Jenkins (i opcionalment SonarQube) en entorns locals i educatius de CI.
**Requisitos:**
- macOS, Linux o Windows con compatibilidad para Docker o Vagrant
- Permisos de ejecución para los scripts (`chmod +x *.sh`)
- **git**: Necesario para clonar el repositorio
- **Vagrant**: Este repositorio utiliza una caja Vagrant basada en Ubuntu y se utilizará APT.
- **Virtualbox**: Es el motor para virtualizar el entorno.
**Requisits:**
- macOS, Linux o Windows amb compatibilitat per a Docker o Vagrant
- Permisos d'execució per als scripts (`chmod +x *.sh`)
- **git**: Necessari per clonar el repositori
- **Vagrant**: Aquest repositori utilitza una caixa Vagrant basada en Ubuntu i es farà servir APT.
- **Virtualbox**: És el motor per virtualitzar l'entorn.
**Estructura del repositorio:**
- `docker.sh` — script para arrancar servicios con Docker
- `jenkins.sh` — script de ayuda para gestionar Jenkins (arrancar, detener, acceder)
- `sonarqube.sh` — script para arrancar SonarQube (opcional)
- `Vagrantfile` — definición para crear una VM con Vagrant que instala Jenkins
**Estructura del repositori:**
- `docker.sh` — script per arrancar serveis amb Docker
- `jenkins.sh` — script d'ajuda per gestionar Jenkins (arrancar, aturar, accedir)
- `sonarqube.sh` — script per arrancar SonarQube (opcional)
- `Vagrantfile` — definició per crear una VM amb Vagrant que instal·la Jenkins
**Inicio rápido (Vagrant)**
**Inici ràpid (Vagrant)**
1) Instala Vagrant y VirtualBox.
2) Inicia la VM definida en el `Vagrantfile`:
1) Instal·la Vagrant i VirtualBox.
2) Inicia la VM definida al `Vagrantfile`:
```bash
vagrant up
vagrant ssh jenkins
# dentro de la VM, sigue las instrucciones del Vagrantfile o de los scripts
# dins de la VM, segueix les instruccions del Vagrantfile o dels scripts
```
**Descripción breve de los scripts:**
- `docker.sh`: crea y gestiona contenedores (Jenkins, posiblemente SonarQube u otros servicios). Revisa su contenido para ajustar puertos y volúmenes.
- `jenkins.sh`: utilidades para obtener la URL de acceso, el usuario inicial y los secrets.
- `sonarqube.sh`: arranca SonarQube en modo desarrollo para escaneos locales.
- `Vagrantfile`: configura una máquina virtual con una instalación mínima para ejecutar Jenkins sin Docker.
**Descripció breu dels scripts:**
- `docker.sh`: crea i gestiona contenidors (Jenkins, possiblement SonarQube u altres serveis). Revisa el seu contingut per ajustar ports i volums.
- `jenkins.sh`: utilitats per obtenir la URL d'accés, l'usuari inicial i els secrets.
- `sonarqube.sh`: arranca SonarQube en mode desenvolupament per a escanejats locals.
- `Vagrantfile`: configura una màquina virtual amb una instal·lació mínima per executar Jenkins sense Docker.
**Puertos por defecto (configurables):**
**Ports per defecte (configurables):**
- Jenkins: 8080
- SonarQube: 9000
## Resolución de problemas
- Si un puerto está ocupado, modifica la configuración del script o libera el puerto.
- Comprueba permisos: `chmod +x *.sh`.
- Revisa logs de los contenedores con `docker logs <container>` o entra con `vagrant ssh` y consulta los logs dentro de la VM.
## Resolució de problemes
- Si un port està ocupat, modifica la configuració del script o allibera el port.
- Comprova permisos: `chmod +x *.sh`.
- Revisa registres dels contenidors amb `docker logs <container>` o entra amb `vagrant ssh` i consulta els registres dins de la VM.
## Contribuir
- Abre un issue para proponer mejoras o reportar bugs.
- Haz fork y envía pull requests con cambios pequeños y bien documentados.
- Obri un issue per proposar millores o reportar bugs.
- Fes fork i envia pull requests amb canvis petits i ben documentats.
## Solución de problemas
## Solució de problemes
Si encuentras problemas al aprovisionar la caja, puedes descargarla directamente y añadirla a Vagrant.
Si trobes problemes en aprovisionar la caixa, pots descarregar-la directament i afegir-la a Vagrant.
## Problemas comunes de red
## Problemes comuns de xarxa
Si tienes proxies o VPNs activos en tu equipo, es posible que Vagrant no pueda aprovisionar el entorno.
Si tens proxies o VPNs actius al teu equip, és possible que Vagrant no pugui aprovisionar l'entorn.
Comprueba tu conectividad previamente.
Comprova la teva connectivitat prèviament.
## Licencia
## Llicència
Este proyecto está publicado bajo la licencia MIT. Modifica según tus necesidades.
Aquest projecte està publicat sota la llicència MIT. Modifica segons les teves necessitats.
Este tutorial ha sido publicado por [Agile611](http://www.agile611.com/) bajo la licencia Creative Commons Atribución-NoComercial 4.0 Internacional.
Aquest tutorial ha estat publicat per [Agile611](http://www.agile611.com/) sota la llicència Creative Commons Atribució-NoComercial 4.0 Internacional.
[![License: CC BY-NC 4.0](https://img.shields.io/badge/License-CC_BY--NC_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc/4.0/)
Aquest `README` va ser originalment escrit per [Guillem Hernández Sola](https://www.linkedin.com/in/guillemhs/) i també es publica en el domini públic.
Este `README` fue originalmente escrito por [Guillem Hernández Sola](https://www.linkedin.com/in/guillemhs/) y también se publica en el dominio público.
Contacta con Agile611 para más detalles.
Contacta amb Agile611 per més detalls.
- [Agile611](http://www.agile611.com/)
- Laureà Miró 309
- 08950 Esplugues de Llobregat (Barcelona)