Skip to main content

How to Archive Build Artifacts to a Network Share in Batch Script

Archiving build artifacts to a network share creates a centralized, accessible repository of every build your team produces. This enables deployment rollbacks, QA testing of specific versions, compliance auditing, and disaster recovery from any build in history. A Batch Script can automate the entire archival process, including versioned directory creation, file transfer, retention policies, and verification.

In this guide, we will explore how to archive build artifacts to network shares from a Batch Script using Robocopy and standard Windows commands.

Method 1: Basic Artifact Archive

@echo off
setlocal

set "source=artifacts\packages"
set "share=\\BuildServer\Artifacts\MyApp"
set "version=1.2.0"

if not exist "%source%\" (
echo [ERROR] Source directory not found: %source%
pause
exit /b 1
)

if not exist "%share%\" (
echo [ERROR] Network share not accessible: %share%
pause
exit /b 1
)

echo Archiving build artifacts...
echo Source: %source%
echo Target: %share%\%version%
echo.

:: Create version directory on share
if not exist "%share%\%version%" mkdir "%share%\%version%"

:: Copy artifacts
robocopy "%source%" "%share%\%version%" /e /r:3 /w:5 /np

if %errorlevel% leq 3 (
echo.
echo [SUCCESS] Artifacts archived to %share%\%version%
) else (
echo.
echo [ERROR] Archive failed. Exit code: %errorlevel%
exit /b 1
)

pause

Method 2: Versioned Archive with Metadata

@echo off
setlocal enabledelayedexpansion

set "source=artifacts"
set "share=\\BuildServer\Artifacts\MyApp"
set "app_name=MyApp"

:: Read version
set "version=0.0.0"
if exist VERSION (
set /p "version=" < VERSION
)

:: Build number
set "build=0"
if exist BUILD_NUMBER (
set /p "build=" < BUILD_NUMBER
)

:: Timestamp
for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "timestamp=%dt:~0,4%%dt:~4,2%%dt:~6,2%_%dt:~8,2%%dt:~10,2%"
set "archive_date=%dt:~0,4%-%dt:~4,2%-%dt:~6,2% %dt:~8,2%:%dt:~10,2%:%dt:~12,2%"

set "archive_dir=%share%\v!version!_b!build!_%timestamp%"

echo =============================================
echo BUILD ARTIFACT ARCHIVE
echo =============================================
echo App: %app_name%
echo Version: !version! (build !build!^)
echo Source: %source%
echo Archive: !archive_dir!
echo =============================================
echo.

:: Verify source exists
if not exist "%source%\" (
echo [ERROR] Source directory not found: %source%
pause
exit /b 1
)

:: Verify network share is accessible
if not exist "%share%\" (
echo [ERROR] Network share not accessible: %share%
echo Check network connectivity and permissions.
pause
exit /b 1
)

:: Create archive directory
mkdir "!archive_dir!" 2>nul

:: Copy artifacts
echo [1/3] Copying artifacts...
robocopy "%source%" "!archive_dir!\artifacts" /e /r:3 /w:5 /np /ndl /nfl >nul
set "robo_result=!errorlevel!"
if !robo_result! gtr 7 (
echo [FAIL] Copy error (robocopy exit: !robo_result!^).
exit /b 1
)
echo Done.

:: Generate metadata file
echo [2/3] Writing metadata...
(
echo app_name=%app_name%
echo version=!version!
echo build=!build!
echo archived=!archive_date!
echo machine=%COMPUTERNAME%
echo user=%USERNAME%
echo source=%source%
) > "!archive_dir!\build_info.txt"

:: Copy git info if available
echo [3/3] Capturing source info...
where git >nul 2>&1
if !errorlevel!==0 (
git rev-parse HEAD > "!archive_dir!\git_commit.txt" 2>nul
git log -1 --pretty=format:"%%H %%s" > "!archive_dir!\git_message.txt" 2>nul
git branch --show-current > "!archive_dir!\git_branch.txt" 2>nul
echo Git info captured.
) else (
echo Git not available. Skipping.
)

echo.
echo =============================================
echo ARCHIVE COMPLETE
echo Location: !archive_dir!
echo =============================================

pause

Method 3: Archive with Retention Policy

Automatically clean old archives to prevent storage bloat:

@echo off
setlocal enabledelayedexpansion

set "share=\\BuildServer\Artifacts\MyApp"
set "keep_count=20"

if not exist "%share%\" (
echo [ERROR] Share not accessible: %share%
pause
exit /b 1
)

echo =============================================
echo ARCHIVE RETENTION CLEANUP
echo Share: %share%
echo Keep: newest %keep_count%
echo =============================================
echo.

:: Count current archives
set "total=0"
for /f "delims=" %%D in ('dir /b /ad /od "%share%\v*" 2^>nul') do set /a total+=1

echo Total archives: !total!

if !total! leq %keep_count% (
echo No cleanup needed (at or under threshold of %keep_count%^).
pause
exit /b 0
)

:: Calculate how many to delete
set /a to_delete=total - keep_count

echo Deleting oldest !to_delete! archive(s^)...
echo.

:: Delete archives beyond retention count (oldest first, sorted by date)
set "count=0"
set "deleted=0"

for /f "delims=" %%D in ('dir /b /ad /od "%share%\v*" 2^>nul') do (
set /a count+=1
if !count! leq !to_delete! (
echo Deleting: %%D
rmdir /s /q "%share%\%%D" 2>nul
if !errorlevel!==0 (
set /a deleted+=1
) else (
echo [FAIL] Could not delete %%D
)
) else (
echo Keeping: %%D
)
)

set /a remaining=total - deleted
echo.
echo Deleted: !deleted! Remaining: !remaining!

pause

Method 4: Multi-Component Archive

Archive multiple build outputs from a solution:

@echo off
setlocal enabledelayedexpansion

set "share=\\BuildServer\Artifacts\MyPlatform"

set "version=0.0.0"
if exist VERSION (
set /p "version=" < VERSION
)

for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "timestamp=%dt:~0,4%%dt:~4,2%%dt:~6,2%"
set "archive_date=%dt:~0,4%-%dt:~4,2%-%dt:~6,2%"

set "archive=%share%\v!version!_%timestamp%"

echo =============================================
echo MULTI-COMPONENT ARCHIVE
echo Target: !archive!
echo =============================================
echo.

if not exist "%share%\" (
echo [ERROR] Share not accessible: %share%
exit /b 1
)

mkdir "!archive!" 2>nul

:: Define components
set "comp_count=4"
set "comps[0]=WebApp"
set "comps[1]=API"
set "comps[2]=WorkerService"
set "comps[3]=Database"

:: Archive each component
set "archived=0"
set "failed=0"
set "skipped=0"
set /a last=comp_count - 1

for /L %%i in (0,1,!last!) do (
set "comp=!comps[%%i]!"
if exist "artifacts\!comp!\" (
echo Archiving !comp!...
robocopy "artifacts\!comp!" "!archive!\!comp!" /e /r:2 /w:3 /np /ndl /nfl >nul
if !errorlevel! leq 3 (
echo [OK]
set /a archived+=1
) else (
echo [FAIL]
set /a failed+=1
)
) else (
echo [SKIP] !comp! (artifacts\!comp! not found^)
set /a skipped+=1
)
)

:: Create manifest
echo.
echo Creating manifest...
(
echo Platform Release v!version!
echo Archived: !archive_date!
echo Machine: %COMPUTERNAME%
echo.
echo Components:
) > "!archive!\MANIFEST.txt"

for /L %%i in (0,1,!last!) do (
set "comp=!comps[%%i]!"
if exist "!archive!\!comp!\" (
echo [x] !comp!>> "!archive!\MANIFEST.txt"
) else (
echo [ ] !comp! (not included^)>> "!archive!\MANIFEST.txt"
)
)

echo.
echo =============================================
echo RESULTS: !archived! archived, !failed! failed, !skipped! skipped
echo =============================================

if !failed! gtr 0 exit /b 1

dir /b "!archive!"

pause

Method 5: Verified Archive with Checksums

Ensure archive integrity with hash verification:

@echo off
setlocal enabledelayedexpansion

set "source=artifacts\packages"
set "share=\\BuildServer\Artifacts\MyApp"
set "version=1.2.0"
set "archive=%share%\v%version%"

if not exist "%source%\" (
echo [ERROR] Source directory not found: %source%
pause
exit /b 1
)

if not exist "%share%\" (
echo [ERROR] Share not accessible: %share%
pause
exit /b 1
)

echo Archiving with integrity verification...
echo.

:: Step 1: Copy to archive
echo [1/3] Copying to archive...
if not exist "%archive%" mkdir "%archive%"
robocopy "%source%" "%archive%" /e /r:3 /w:5 /np /ndl /nfl >nul
set "robo_result=!errorlevel!"
if !robo_result! gtr 7 (
echo [FAIL] Copy error.
exit /b 1
)
echo Done.

:: Step 2: Generate checksums from the archived copies
echo [2/3] Computing checksums...
set "checksum_file=%archive%\SHA256SUMS.txt"
if exist "!checksum_file!" del "!checksum_file!"

set "file_count=0"
for %%F in ("%archive%\*.*") do (
if /i not "%%~nxF"=="SHA256SUMS.txt" (
set /a file_count+=1
for /f "skip=1 delims=" %%H in ('certutil -hashfile "%%F" SHA256 2^>nul') do (
echo %%H | findstr /r "^[0-9a-f]" >nul 2>&1
if !errorlevel!==0 (
echo %%H %%~nxF>> "!checksum_file!"
)
)
)
)

echo Checksums computed for !file_count! files.

:: Step 3: Verify by re-hashing
echo [3/3] Verifying archive integrity...
set "verified=0"
set "verify_failed=0"

for /f "tokens=1,*" %%H in ('type "!checksum_file!"') do (
set "expected=%%H"
set "filename=%%I"
set "matched=0"

for /f "skip=1 delims=" %%V in ('certutil -hashfile "%archive%\!filename!" SHA256 2^>nul') do (
echo %%V | findstr /r "^[0-9a-f]" >nul 2>&1
if !errorlevel!==0 if !matched!==0 (
if "%%V"=="!expected!" (
echo [OK] !filename!
set /a verified+=1
) else (
echo [FAIL] !filename! (checksum mismatch^)
set /a verify_failed+=1
)
set "matched=1"
)
)
)

echo.
if !verify_failed!==0 (
echo [SUCCESS] Archive verified. All !verified! files match.
) else (
echo [ERROR] !verify_failed! file(s^) failed verification.
exit /b 1
)

pause

Common Mistakes

The Wrong Way: Archiving Without Version Identification

:: WRONG - Overwrites previous archive with no version info
robocopy artifacts \\server\share\latest /mir
:: Previous build artifacts are lost

Output Concern: Without versioned directory names, each archive overwrites the previous one. Use version numbers, build numbers, and timestamps in the directory name to maintain a complete history.

The Wrong Way: No Network Connectivity Check

:: WRONG - Fails silently if network is down
robocopy artifacts \\server\share\v1.0 /e
:: May fail with cryptic errors if the share is unreachable

Always verify the network share is accessible before attempting to copy. Check with if not exist "\\server\share\" or net use before proceeding.

Best Practices

  1. Include version and timestamp in directory names: Makes each archive uniquely identifiable.
  2. Add metadata files: Record version, build number, commit hash, and build date.
  3. Implement retention policies: Automatically clean old archives to manage storage.
  4. Verify after copying: Confirm file integrity with checksums or file counts.
  5. Check network accessibility first: Detect connectivity issues before starting the archive.

Conclusion

Archiving build artifacts to a network share from a Batch Script creates a versioned history of every build, enabling rollbacks, auditing, and cross-team access to any version.

By combining Robocopy for reliable file transfer, versioned directory structures for organization, metadata files for traceability, retention policies for storage management, and checksum verification for integrity, teams build a complete artifact management system that preserves the full build history while keeping storage consumption under control.