01e - Varie Programmazione IBM i

Analisi statica del codice sorgente Cobol e RPG su IBM i con SonarQube

In informatica, l’analisi statica del programma (o, semplicemente, analisi statica) è l’analisi del codice sorgente realizzata senza eseguire i programmi (a differenza dell’analisi dinamica dei programmi, che viene eseguita durante la loro esecuzione).

Questo processo fornisce una comprensione della struttura del codice sorgente e può aiutare a garantire che il codice aderisca agli standard del settore (conformità, sicurezza e protezione).

Esistono strumenti che possono aiutare programmatori e sviluppatori ad eseguire l’analisi statica ispezionando il codice alla ricerca di potenziali errori di programmazione (bug), violazioni degli standard di codifica, vulnerabilità di sicurezza e altro ancora.

SonarQube

SonarQube è in grado di eseguire l’analisi di diversi linguaggi a seconda dell’edizione in uso. I linguaggi Cobol e RPG per IBM i sono disponibili solo nelle edizioni Enterprise e Data Center.

Per poter analizzare il codice sorgente, SonarQube deve, ovviamente, potervi accedere. SonarQube non è in grado di accedere ai membri dei vostri file fisici sorgente memorizzati sul file system a librerie dei sistemi IBM i, come genericamente indicato nella sezione “Source code extraction” della documentazione di SonarQube relativa al linguaggio Cobol:

Per analizzare il tuo codice sorgente con SonarQube devi prima estrarlo su un filesystem. Puoi utilizzare un tuo strumento o uno strumento open source; SonarSource non fornisce alcun connettore o strumento di estrazione del codice sorgente.

Sui sistemi IBM i, un filesystem accessibile da SonarQube è l’Integrated File System. Non ci resta, quindi, che copiare il nostro codice sorgente su IFS e renderlo disponibile ai sistemi esterni (nello specifico, il sistema sul quale verrà eseguita l’analisi del codice con il comando sonar-scanner, vedi più avanti).

Per esportare il codice sorgente su IFS, possiamo utilizzare il comando CPYSRC2IFS mentre per renderlo disponibile ai sistemi esterni possiamo utilizzare l’IBM i NetServer.

CPYSCR2IFS e IBM i NetServer

CPYSRC2IFS è un comando che permette di copiare il codice sorgente dai membri di file fisici sorgente ai file di flusso nelle directory IFS dove applicativi di altre piattaforme, tramite la condivisione di rete fornita dalla componente NetServer di IBM i, possono accedervi.

CPYSCR2IFS e IBM i NetServer forniscono il ponte tra il tradizionale ambiente di sviluppo IBM i (PDM/SEU) e strumenti aperti come SonarQube.

Una volta reso disponibile il codice sorgente, è possibile procedere con l’analisi.

Utilizzo di SonarQube

Prima di avviare una scansione, è necessario creare un progetto.

Il progetto può utilizzare la tua piattaforma DevOps di riferimento (Azure, Bitbucket, GitHub o GitLab) come repository del codice sorgente o utilizzare un repository locale (questo è il nostro caso):

Inseriamo alcune informazioni generali sul progetto:

Selezioniamo il tipo di repository del codice sorgente (nel nostro caso selezioniamo un repository locale):

Creiamo il token di identificazione del progetto:

Dopo aver premuto su “Generate” viene visualizzato il token identificativo:

Forniamo ulteriori informazioni sul progetto necessaria allo strumento di analisi:

A fronte delle indicazioni inserite, SonarQube fornisce il comando sonar-scanner da eseguire su di un sistema Windows per lanciare la scansione del codice sorgente per il progetto CBLPRJ01 appena creato:

sonar-scanner.bat -D"sonar.projectKey=CBLPRJ01" -D"sonar.sources=." -D"sonar.host.url=http://{SonarQube_hostname}:{port}" -D"sonar.login=sqp_2508f4480e88c8bcc75aa7ec9ed8a41aa75c04e1"

Se come sistema operativo avessimo selezionato Linux allora il comando suggerito sarebbe stato il seguente:

sonar-scanner \
-Dsonar.projectKey=CBLPRJ01 \
-Dsonar.sources=. \
-Dsonar.host.url=http://{SonarQube_hostname}:{port} \
-Dsonar.login=sqp_2508f4480e88c8bcc75aa7ec9ed8a41aa75c04e1

Nota. {SonarQube_hostname} è il nome host o l’indirizzo ip della tua istanza SonarQube e {port} la porta sulla quale l’istanza SonarQube è in ascolto (la porta di default è 9000).

Cliccando sul link official documentation of the Scanner verremo reindirizzati alla pagina di download di SonarScanner, lo strumento di scansione e anlisi del codice di SonarQube, dove sarà possibile scaricare la versione in base al sistema operativo sul quale verrà eseguito:

Nel nostro caso, la piattaforma utilizzata per l’analisi del codice sorgente è Windows 64-bit e la versione di SonarScanner scaricata è la 4.7.0.2747.

Nota. La pagina di download di SonarScanner contiene anche utili indicazioni sulla configurazione del progetto (file sonar-project.properties), sull’esecuzione di SonarScanner dall’archivio zip o dall’immagine Docker, sulle possibili alternative all’utilizzo del file sonar-project.properties ed altre informazioni.

Al termine del download dovremo estrarre il contenuto dell’archivio ed impostare il percorso della directory bin appena estratta nella variabile d’ambiente PATH:

  • Sui sistemi Windows è possibile impostare la variabile di ambiente Path dal prompt dei comandi di Windows utilizzando il comando set o setx. Il comando set imposta solo la variabile di ambiente per la sessione corrente. Il comando setx lo imposta in modo permanente, ma non per la sessione corrente (se si desidera impostarlo per le sessioni correnti e future, utilizzare sia setx che set). In alternativa, è possibile impostare la variabile d’ambiente anche dal menu attività Power User facendo clic con il pulsante destro del mouse sul menu Start di Windows quindi selezioando “Sistema”, poi “Impostazioni di sistema avanzate”, “Variabili d’ambiente” e selezionando la variabile d’ambiente “Percorso” quindi premendo su “Modifica”.
  • Sui sistemi Linux è posssibile aggiungere la directory /var/opt/sonar-scanner-4.7.0.2747-linux/bin alla variabile di ambiente PATH:
$ export PATH=$PATH:/var/opt/sonar-scanner-4.7.0.2747-linux/bin

$ ln -s /var/opt/sonar-scanner-4.7.0.2747-linux/bin/sonar-scanner /usr/local/bin/

Preparazione all’analisi del codice sorgente

Nell’articolo assumiamo che il nostro codice sorgente (programmi e copie) sia memorizzato su file di flusso su IFS nelle directory Src e Cpy e che la directory che le contiene sia condivisa tramite NetServer.

Analisi del codice sorgente con SonarScanner

sonar-scanner è il comando che possiamo utilizzare per analizzare il nostro codice sorgente e per inviare l’esito dell’analisi a SonarQube. Una volta installato lo strumento, dobbiamo configurarlo creando il file sonar-project.properties a livello di root del progetto:

Il file sonar-project.properties contiene il nome dell’host dell’istanza di SonarQube, la chiave del progetto per identificare il progetto in SonarQube e le informazioni sui file di origine (come i suffissi delle estensioni dei file, la posizione dell’origine, ecc.). Vediamo un esempio:

# ----------------------------------------
# SonarQube Host
# Note: Default port is 9000
# ----------------------------------------
sonar.host.url=http://{SonarQube_hostname}:{port}

# ----------------------------------------
# Project identification
# Note: The key is generated by the SonarQube project admin.
# ----------------------------------------
sonar.projectKey=CBLPRJ01
sonar.projectName=CBLPRJ01

# ----------------------------------------
# Cobol dialect
# ----------------------------------------
# Cobol/400
sonar.cobol.dialect=ibm-cobol/400
# Cobol ILE
#sonar.cobol.dialect=ibm-ile-cobol

# ----------------------------------------
# Language-dependent attributes
# ----------------------------------------
#sonar.cobol.sourceFormat=fixed
#sonar.cobol.tab.width=8

# ----------------------------------------
# Source information
# Note: This assumes that your source is downloaded into a directory
# named "Src" 
# ----------------------------------------
sonar.sources=./Src
sonar.cobol.file.suffixes= CBL,SQLCBL,CPY

# ----------------------------------------
# Copy information
# Note: This assumes that your source is downloaded into a directory
# named "Cpy"
# ----------------------------------------
sonar.cobol.copy.directories=./Cpy
sonar.cobol.copy.suffixes= CBL,SQLCBL,CPY

# ----------------------------------------
# Generic attributes
# ----------------------------------------
# Excludes all files from the test coverage metrics
sonar.coverage.exclusions=**/*.*

Nota. Code coverage (copertura del codice) descrive la percentuale di codice interessata dai test automatici. In altre parole, controlla quali parti di codice vengono eseguite durante i test e quali no. In sostanza, è una metrica utilizzata per verificare la qualità dei test, perché rappresenta la percentuale del codice di produzione che è stato testato ed eseguito. SonarQube è utilizzato in integrazione con JaCoCo, una libreria gratuita di copertura del codice per Java. Siccome questa funzionalità non viene utilizzata preferisco disattivarla per evitare noiose segnalazioni durante la navigazione del codice sorgente dall’interfaccia web di SonarQube.

Una volta configurato il file sonar-project.properties, possiamo eseguire la scansione del codice sorgente utilizzando il comando sonar-scanner dalla finestra del prompt dei comandi:

> m:
> cd \CBLPRJ01
> sonar-scanner.bat -D"sonar.login=sqp_2508f4480e88c8bcc75aa7ec9ed8a41aa75c04e1"

Nel nostro caso, m: è il disco che punta alla condivisione di rete dal sistema IBM i dove si trova il codice sorgente da analizzare, esportato con il comando CPYSRC2IFS.

Nota. Le configurazioni presenti nel file sonar-project.properties possono essere passate come parametri al comando sonar-scanner come segue, eliminando così la necessità di utilizzare il file:

> sonar-scanner.bat -D"sonar.login=sqp_2508f4480e88c8bcc75aa7ec9ed8a41aa75c04e1" -D"sonar.host.url=http://{SonarQube_hostname}:{port}" -D"sonar.projectKey=CBLPRJ01" -D"sonar.projectName=CBLPRJ01" -D"sonar.cobol.dialect=ibm-cobol/400" -D"sonar.sources=./Src" -D"sonar.cobol.file.suffixes= CBL,SQLCBL,CPY" -D"sonar.cobol.copy.directories=./Cpy" -D"sonar.cobol.copy.suffixes= CBL,SQLCBL,CPY" -D"sonar.coverage.exclusions=**/*.*"

Di seguito l’output del comando sonar-scanner:

INFO: Scanner configuration file: C:\MyPrograms\sonar-scanner-4.7.0.2747-windows\bin\..\conf\sonar-scanner.properties
INFO: Project root configuration file: m:\CBLPRJ01\sonar-project.properties
INFO: SonarScanner 4.7.0.2747
INFO: Java 11.0.14.1 Eclipse Adoptium (64-bit)
INFO: Windows 10 10.0 amd64
INFO: User cache: C:\Users\xxxxxxxx\.sonar\cache
INFO: Scanner configuration file: C:\MyPrograms\sonar-scanner-4.7.0.2747-windows\bin\..\conf\sonar-scanner.properties
INFO: Project root configuration file: m:\CBLPRJ01\sonar-project.properties
INFO: Analyzing on SonarQube server 9.7.1.62043
INFO: Default locale: "it_IT", source code encoding: "windows-1252" (analysis is platform dependent)
INFO: Load global settings
INFO: Load global settings (done) | time=66ms
INFO: Server id: 147B411E-AYRcQ0q0f13ET8K16xxa
INFO: User cache: C:\Users\xxxxxxxx\.sonar\cache
INFO: Load/download plugins
INFO: Load plugins index
INFO: Load plugins index (done) | time=55ms
INFO: Load/download plugins (done) | time=7608ms
INFO: Loaded core extensions: developer-scanner
INFO: Process project properties
INFO: Process project properties (done) | time=23ms
INFO: Execute project builders
INFO: Execute project builders (done) | time=2ms
INFO: Project key: CBLPRJ01
INFO: Base dir: M:\CBLPRJ01
INFO: Working dir: m:\CBLPRJ01\.scannerwork
INFO: Load project settings for component key: 'CBLPRJ01'
INFO: Load project settings for component key: 'CBLPRJ01' (done) | time=39ms
INFO: Load project branches
INFO: Load project branches (done) | time=22ms
INFO: Load project pull requests
INFO: Load project pull requests (done) | time=11ms
INFO: Load branch configuration
INFO: Load branch configuration (done) | time=3ms
WARN: SCM provider autodetection failed. Please use "sonar.scm.provider" to define SCM of your project, or disable the SCM Sensor in the project settings.
INFO: Load quality profiles
INFO: Load quality profiles (done) | time=69ms
INFO: Load active rules
INFO: Load active rules (done) | time=3211ms
INFO: Load analysis cache
INFO: Load analysis cache (404) | time=9ms
INFO: Load project repositories
INFO: Load project repositories (done) | time=28ms
INFO: Indexing files...
INFO: Project configuration:
INFO: 1 file indexed
INFO: Quality profile for cobol: Sonar way
INFO: ------------- Run sensors on module CBLPRJ01
INFO: Load metrics repository
INFO: Load metrics repository (done) | time=55ms
INFO: Sensor CobolSquidSensor [cobol]
INFO: About to analyse COBOL Programs using 'ibm-cobol/400' dialect and 'fixed' source code format.
INFO: Found empty cache on server
INFO: 1 source file to be analyzed
INFO: 1/1 source file has been analyzed
INFO: Analysis time: 454ms
INFO: 1 source file to be highlighted and measured
INFO: 1/1 source file has been highlighted and measured
INFO: Decoration time: 58ms
INFO: Cache: 0/1 hits, 0/1 decorator hits, 12226 bytes
INFO: Sensor CobolSquidSensor [cobol] (done) | time=514ms
INFO: Sensor C# Project Type Information [csharp]
INFO: Sensor C# Project Type Information [csharp] (done) | time=1ms
INFO: Sensor C# Analysis Log [csharp]
INFO: Sensor C# Analysis Log [csharp] (done) | time=10ms
INFO: Sensor C# Properties [csharp]
INFO: Sensor C# Properties [csharp] (done) | time=0ms
INFO: Sensor HTML [web]
INFO: Sensor HTML [web] (done) | time=2ms
INFO: Sensor Text Sensor [text]
INFO: 1 source file to be analyzed
INFO: 1/1 source file has been analyzed
INFO: Sensor Text Sensor [text] (done) | time=7ms
INFO: Sensor VB.NET Project Type Information [vbnet]
INFO: Sensor VB.NET Project Type Information [vbnet] (done) | time=1ms
INFO: Sensor VB.NET Analysis Log [vbnet]
INFO: Sensor VB.NET Analysis Log [vbnet] (done) | time=10ms
INFO: Sensor VB.NET Properties [vbnet]
INFO: Sensor VB.NET Properties [vbnet] (done) | time=1ms
INFO: Sensor JaCoCo XML Report Importer [jacoco]
INFO: 'sonar.coverage.jacoco.xmlReportPaths' is not defined. Using default locations: target/site/jacoco/jacoco.xml,target/site/jacoco-it/jacoco.xml,build/reports/jacoco/test/jacocoTestReport.xml
INFO: No report imported, no coverage information will be imported by JaCoCo XML Report Importer
INFO: Sensor JaCoCo XML Report Importer [jacoco] (done) | time=10ms
INFO: Sensor CSS Rules [javascript]
INFO: No CSS, PHP, HTML or VueJS files are found in the project. CSS analysis is skipped.
INFO: Sensor CSS Rules [javascript] (done) | time=2ms
INFO: Sensor ThymeLeaf template sensor [securityjavafrontend]
INFO: Sensor ThymeLeaf template sensor [securityjavafrontend] (done) | time=3ms
INFO: Sensor Serverless configuration file sensor [security]
INFO: 0 Serverless function entries were found in the project
INFO: 0 Serverless function handlers were kept as entrypoints
INFO: Sensor Serverless configuration file sensor [security] (done) | time=9ms
INFO: Sensor AWS SAM template file sensor [security]
INFO: Sensor AWS SAM template file sensor [security] (done) | time=0ms
INFO: Sensor AWS SAM Inline template file sensor [security]
INFO: Sensor AWS SAM Inline template file sensor [security] (done) | time=0ms
INFO: Sensor javabugs [dbd]
INFO: Reading IR files from: m:\CBLPRJ01\.scannerwork\ir\java
INFO: No IR files have been included for analysis.
INFO: Sensor javabugs [dbd] (done) | time=3ms
INFO: Sensor pythonbugs [dbd]
INFO: Reading IR files from: m:\CBLPRJ01\.scannerwork\ir\python
INFO: No IR files have been included for analysis.
INFO: Sensor pythonbugs [dbd] (done) | time=6ms
INFO: Sensor JavaSecuritySensor [security]
INFO: Reading type hierarchy from: m:\CBLPRJ01\.scannerwork\ucfg2\java
INFO: Read 0 type definitions
INFO: Reading UCFGs from: m:\CBLPRJ01\.scannerwork\ucfg2\java
INFO: No UCFGs have been included for analysis.
INFO: Sensor JavaSecuritySensor [security] (done) | time=7ms
INFO: Sensor CSharpSecuritySensor [security]
INFO: Reading type hierarchy from: m:\CBLPRJ01\ucfg_cs2
INFO: Read 0 type definitions
INFO: Reading UCFGs from: m:\CBLPRJ01\ucfg_cs2
INFO: No UCFGs have been included for analysis.
INFO: Sensor CSharpSecuritySensor [security] (done) | time=3ms
INFO: Sensor PhpSecuritySensor [security]
INFO: Reading type hierarchy from: m:\CBLPRJ01\.scannerwork\ucfg2\php
INFO: Read 0 type definitions
INFO: Reading UCFGs from: m:\CBLPRJ01\.scannerwork\ucfg2\php
INFO: No UCFGs have been included for analysis.
INFO: Sensor PhpSecuritySensor [security] (done) | time=3ms
INFO: Sensor PythonSecuritySensor [security]
INFO: Reading type hierarchy from: m:\CBLPRJ01\.scannerwork\ucfg2\python
INFO: Read 0 type definitions
INFO: Reading UCFGs from: m:\CBLPRJ01\.scannerwork\ucfg2\python
INFO: No UCFGs have been included for analysis.
INFO: Sensor PythonSecuritySensor [security] (done) | time=4ms
INFO: Sensor JsSecuritySensor [security]
INFO: Reading type hierarchy from: m:\CBLPRJ01\.scannerwork\ucfg2\js
INFO: Read 0 type definitions
INFO: Reading UCFGs from: m:\CBLPRJ01\.scannerwork\ucfg2\js
INFO: No UCFGs have been included for analysis.
INFO: Sensor JsSecuritySensor [security] (done) | time=4ms
INFO: ------------- Run sensors on project
INFO: Sensor Analysis Warnings import [csharp]
INFO: Sensor Analysis Warnings import [csharp] (done) | time=1ms
INFO: Sensor Zero Coverage Sensor
INFO: Sensor Zero Coverage Sensor (done) | time=16ms
INFO: SCM Publisher No SCM system was detected. You can use the 'sonar.scm.provider' property to explicitly specify it.
INFO: CPD Executor Calculating CPD for 1 file
INFO: CPD Executor CPD calculation finished (done) | time=10ms
INFO: Analysis report generated in 168ms, dir size=241.3 kB
INFO: Analysis report compressed in 3084ms, zip size=42.9 kB
INFO: Analysis report uploaded in 63ms
INFO: ANALYSIS SUCCESSFUL, you can find the results at: http://{SonarQube_hostname}:{port}/dashboard?id=CBLPRJ01
INFO: Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
INFO: More about the report processing at http://{SonarQube_hostname}:{port}/api/ce/task?id=AYSaBuDP2lfWAptP6Djs
INFO: Analysis total time: 12.356 s
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 22.474s
INFO: Final Memory: 37M/124M
INFO: ------------------------------------------------------------------------

Al termine della scansione, è possibile navigare nel progetto dall’interfaccia web di SonarQube e visualizzare i risultati (l’output di sonar-scanner fornisce l’URL da copiare nel browser, nel nostro caso: http://{SonarQube_hostname}:{port}/dashboard?id=CBLPRJ01):

Il codice sorgente ha superato l’analisi ma bisogna lavorare sull’affidabilità (5 bugs riscontrati).

Utilizzando gli strumenti di analisi statica del codice puoi assicurarti che il codice sia conforme alle linee guida di stile e codifica e, cosa più importante, che sia “pulito” e privo di problemi prima di essere distribuito.

Appendice: Configurazione del progetto SonarQube per linguaggio RPG

Per il linguaggio RPG, il file sonar-project.properties dovrebbe essese simile a questo:

# ----------------------------------------
# SonarQube Host 
# Note: Default port is 9000
# ----------------------------------------
sonar.host.url=http://{SonarQube_hostname}:{port}

# ----------------------------------------
# Project identification
# Note: The key is generated by the SonarQube project admin.
# ----------------------------------------
sonar.projectKey=RPGPRJ01
sonar.projectName=RPGPRJ01

# ----------------------------------------
# Language-dependent attributes
# ----------------------------------------
sonar.rpg.leftMarginWidth=0

# ----------------------------------------
# Source information
# Note: This assumes that your source is downloaded into a directory
# named "Src" 
# ----------------------------------------
sonar.sources=./Src
# sonar.rpg.suffixes=.rpg,.rpgle,.sqlrpgle,.RPG,.RPGLE,.SQLRPGLE

# ----------------------------------------
# Generic attributes
# ----------------------------------------
# Excludes all files from the test coverage metrics
sonar.coverage.exclusions=**/*.*
Related Posts
Esportare codice sorgente su IFS

Se hai la necessità di esportare su IFS i sorgenti di programmi memorizzati su membri di file sorgente allora il Read more

Visual Studio Code – Code for IBM i

Visual Studio Code è un editor di sviluppo gratuito che ci permette di iniziare a programmare in qualsiasi linguaggio di Read more

IFS – Cercare files e directories

Approfitto di una domanda fatta sui gruppi di discussione Midrange.com (Is there an easy way to find a file in Read more

Recent Posts

Gestione dei file video bloccati su IBM i: una soluzione efficace

Riceviamo e pubblichiamo ben volentieri questo "tip & trick" di Patrick Rizzi che presenta una tecnica che permette di intervenire…

2 settimane ago

Monitoraggio Messaggi QSYSOPR: SQL per Ottenere Messaggi e Reply

Prendo spunto da una risposta di Michael Mayer sulle mailing list di Midrange.com a chi chiedeva come monitorare i messaggi…

2 settimane ago

Perché l’ERP è la Chiave del Successo per le Imprese Moderne

Le imprese sono sempre più alla ricerca di strumenti che possano migliorare l'efficienza, la collaborazione e la gestione delle risorse.…

2 mesi ago

ACS Access Client Solution 1.1.9.5

I primi di Aprile è uscita la "Spring Version" di ACS Access Client Solution, versione 1.1.9.5 Interessanti novità soprattutto in…

7 mesi ago

Tim Rowe and Scott Forstie – Promo video for CEC 2024 – Milan

Se non vi bastava la ricca agenda delle sessioni del Common Europe Congress 2024, 3-6 Giugno Milano, ecco un altro…

7 mesi ago

Code for IBM i 2.10.0 – Debug IBM i con Visual Studio Code

Le funzioni di debug con Visual Studio Code sono disponibili da qualche tempo ma questa nuova versione 2.10.0 semplifica la…

7 mesi ago