Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,38 @@ jobs:
cd ..
shell: bash

- name: Generate SHA256 checksum (Unix)
if: matrix.goos != 'windows'
run: |
cd dist
ARCHIVE_NAME="dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}"
if command -v sha256sum &> /dev/null; then
sha256sum "$ARCHIVE_NAME" > "$ARCHIVE_NAME.sha256"
else
shasum -a 256 "$ARCHIVE_NAME" > "$ARCHIVE_NAME.sha256"
fi
echo "Generated checksum:"
cat "$ARCHIVE_NAME.sha256"
shell: bash

- name: Generate SHA256 checksum (Windows)
if: matrix.goos == 'windows'
run: |
$archiveName = "dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}"
$archivePath = "dist/$archiveName"
$hash = (Get-FileHash -Path $archivePath -Algorithm SHA256).Hash.ToLower()
"$hash $archiveName" | Out-File -FilePath "dist/$archiveName.sha256" -Encoding ASCII -NoNewline
Write-Host "Generated checksum:"
Get-Content "dist/$archiveName.sha256"
shell: pwsh

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.asset_name_suffix }}
path: dist/dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}
path: |
dist/dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}
dist/dtvem-${{ github.event.inputs.version }}-${{ matrix.asset_name_suffix }}.${{ matrix.archive_ext }}.sha256
retention-days: 1

- name: Upload install scripts (linux-amd64 only)
Expand Down Expand Up @@ -274,10 +301,15 @@ jobs:
tag_name: v${{ github.event.inputs.version }}
files: |
artifacts/build-linux-amd64/dtvem-${{ github.event.inputs.version }}-linux-amd64.tar.gz
artifacts/build-linux-amd64/dtvem-${{ github.event.inputs.version }}-linux-amd64.tar.gz.sha256
artifacts/build-macos-amd64/dtvem-${{ github.event.inputs.version }}-macos-amd64.tar.gz
artifacts/build-macos-amd64/dtvem-${{ github.event.inputs.version }}-macos-amd64.tar.gz.sha256
artifacts/build-macos-arm64/dtvem-${{ github.event.inputs.version }}-macos-arm64.tar.gz
artifacts/build-macos-arm64/dtvem-${{ github.event.inputs.version }}-macos-arm64.tar.gz.sha256
artifacts/build-windows-amd64/dtvem-${{ github.event.inputs.version }}-windows-amd64.zip
artifacts/build-windows-amd64/dtvem-${{ github.event.inputs.version }}-windows-amd64.zip.sha256
artifacts/build-windows-arm64/dtvem-${{ github.event.inputs.version }}-windows-arm64.zip
artifacts/build-windows-arm64/dtvem-${{ github.event.inputs.version }}-windows-arm64.zip.sha256
install.sh
install.ps1
body: |
Expand Down Expand Up @@ -314,7 +346,8 @@ jobs:

## Checksums

See the assets below for SHA256 checksums.
SHA256 checksums are provided for each archive (`.sha256` files).
The installers automatically verify checksums before extraction.
draft: false
prerelease: false
generate_release_notes: true # GitHub will auto-generate additional notes
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/script-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ jobs:
shell: pwsh
run: |
Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser
$results = Invoke-ScriptAnalyzer -Path ./install.ps1 -Severity Error,Warning
# Exclude PSAvoidUsingWriteHost - Write-Host is intentional for colored installer output
$results = Invoke-ScriptAnalyzer -Path ./install.ps1 -Severity Error,Warning -ExcludeRule PSAvoidUsingWriteHost,PSUseBOMForUnicodeEncodedFile
if ($results) {
$results | Format-Table -AutoSize
exit 1
Expand Down
49 changes: 49 additions & 0 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,34 @@ function Get-LatestVersion {
}
}

function Test-Checksum {
param(
[string]$FilePath,
[string]$ChecksumPath
)

if (-not (Test-Path $ChecksumPath)) {
Write-Error-Custom "Checksum file not found: $ChecksumPath"
return $false
}

# Read expected hash from checksum file (format: "hash filename")
$checksumContent = Get-Content $ChecksumPath -Raw
$expectedHash = ($checksumContent -split '\s+')[0].ToLower()

# Calculate actual hash
$actualHash = (Get-FileHash -Path $FilePath -Algorithm SHA256).Hash.ToLower()

if ($expectedHash -ne $actualHash) {
Write-Error-Custom "Checksum verification failed!"
Write-Error-Custom "Expected: $expectedHash"
Write-Error-Custom "Actual: $actualHash"
return $false
}

return $true
}

function Main {
Write-Host ""
Write-Host "========================================" -ForegroundColor Blue
Expand Down Expand Up @@ -105,6 +133,27 @@ function Main {
exit 1
}

# Download and verify checksum
$CHECKSUM_URL = "$DOWNLOAD_URL.sha256"
$CHECKSUM_PATH = Join-Path $TMP_DIR "$ARCHIVE_NAME.sha256"

Write-Info "Downloading checksum..."
try {
Invoke-WebRequest -Uri $CHECKSUM_URL -OutFile $CHECKSUM_PATH -UseBasicParsing
}
catch {
Write-Error-Custom "Failed to download checksum file: $_"
Write-Error-Custom "URL: $CHECKSUM_URL"
exit 1
}

Write-Info "Verifying checksum..."
if (-not (Test-Checksum -FilePath $ARCHIVE_PATH -ChecksumPath $CHECKSUM_PATH)) {
Write-Error-Custom "Archive integrity check failed - aborting installation"
exit 1
}
Write-Success "Checksum verified"

# Extract archive
Write-Info "Extracting archive..."
Expand-Archive -Path $ARCHIVE_PATH -DestinationPath $TMP_DIR -Force
Expand Down
63 changes: 59 additions & 4 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,41 @@ download() {
fi
}

# Verify SHA256 checksum
verify_checksum() {
local file=$1
local checksum_file=$2

if [ ! -f "$checksum_file" ]; then
error "Checksum file not found: $checksum_file"
return 1
fi

# Extract expected hash from checksum file (format: "hash filename")
local expected_hash
expected_hash=$(awk '{print $1}' "$checksum_file")

# Calculate actual hash
local actual_hash
if command -v sha256sum &> /dev/null; then
actual_hash=$(sha256sum "$file" | awk '{print $1}')
elif command -v shasum &> /dev/null; then
actual_hash=$(shasum -a 256 "$file" | awk '{print $1}')
else
warning "Neither sha256sum nor shasum found - skipping checksum verification"
return 0
fi

if [ "$expected_hash" != "$actual_hash" ]; then
error "Checksum verification failed!"
error "Expected: $expected_hash"
error "Actual: $actual_hash"
return 1
fi

return 0
}

main() {
echo ""
echo -e "${BLUE}========================================${NC}"
Expand Down Expand Up @@ -138,7 +173,7 @@ main() {

# Create temporary directory
TMP_DIR=$(mktemp -d)
trap "rm -rf $TMP_DIR" EXIT
trap 'rm -rf $TMP_DIR' EXIT

# Download archive
info "Downloading dtvem..."
Expand All @@ -152,6 +187,24 @@ main() {

success "Downloaded successfully"

# Download and verify checksum
CHECKSUM_URL="${DOWNLOAD_URL}.sha256"
CHECKSUM_PATH="$TMP_DIR/${ARCHIVE_NAME}.sha256"

info "Downloading checksum..."
if ! download "$CHECKSUM_URL" "$CHECKSUM_PATH"; then
error "Failed to download checksum file"
error "URL: $CHECKSUM_URL"
exit 1
fi

info "Verifying checksum..."
if ! verify_checksum "$ARCHIVE_PATH" "$CHECKSUM_PATH"; then
error "Archive integrity check failed - aborting installation"
exit 1
fi
success "Checksum verified"

# Extract archive
info "Extracting archive..."
tar -xzf "$ARCHIVE_PATH" -C "$TMP_DIR"
Expand Down Expand Up @@ -213,9 +266,11 @@ main() {
if [ -n "$SHELL_CONFIG" ]; then
# Check if already in config
if ! grep -q "$INSTALL_DIR" "$SHELL_CONFIG" 2>/dev/null; then
echo "" >> "$SHELL_CONFIG"
echo "# Added by dtvem installer" >> "$SHELL_CONFIG"
echo "$EXPORT_CMD" >> "$SHELL_CONFIG"
{
echo ""
echo "# Added by dtvem installer"
echo "$EXPORT_CMD"
} >> "$SHELL_CONFIG"
success "Added to $SHELL_CONFIG"
else
info "Already in $SHELL_CONFIG"
Expand Down