From 5bd4f372e7140fe4290f42fdbda24b88d6d5be4b Mon Sep 17 00:00:00 2001 From: Diogo Mendes Matsubara Date: Thu, 22 Jan 2026 17:15:41 +0100 Subject: [PATCH 1/3] Add workflow: Update latest downloads on download.eclipse.org - New GitHub Actions workflow to replace Jenkins 'Downloads - update latest' job - Accepts version parameter via workflow_dispatch - Uses SSH/SCP to connect to projects-storage.eclipse.org via genie.zenoh user - Copies all zenoh-z*/version/* to zenoh-z*/latest/ for specified version - Includes verification and error handling - Requires SSH_PRIVATE_KEY and SSH_PASSPHRASE secrets - See README for setup instructions --- .github/workflows/update-latest-downloads.yml | 81 +++++++++++++++++++ README.md | 44 ++++++++++ 2 files changed, 125 insertions(+) create mode 100644 .github/workflows/update-latest-downloads.yml diff --git a/.github/workflows/update-latest-downloads.yml b/.github/workflows/update-latest-downloads.yml new file mode 100644 index 00000000..aafb2d5a --- /dev/null +++ b/.github/workflows/update-latest-downloads.yml @@ -0,0 +1,81 @@ +name: Update latest downloads on download.eclipse.org + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to mark as latest (e.g., 1.7.2)' + required: true + type: string + +jobs: + update-latest: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v4.1.1 + + - name: Setup SSH key + run: | + mkdir -p ~/.ssh + echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519 + chmod 600 ~/.ssh/id_ed25519 + echo "${{ secrets.SSH_PASSPHRASE }}" | ssh-add ~/.ssh/id_ed25519 2>/dev/null || true + + - name: Update latest symlinks on download.eclipse.org + run: | + ssh -o StrictHostKeyChecking=no \ + -o UserKnownHostsFile=/dev/null \ + genie.zenoh@projects-storage.eclipse.org \ + " + set -e + VERSION='${{ inputs.version }}' + BASE_PATH='/home/data/httpd/download.eclipse.org/zenoh' + UPDATED_COUNT=0 + + echo '๐Ÿ” Scanning for zenoh packages with version \$VERSION...' + for i in \$BASE_PATH/z*/\$VERSION; do + if [ -d \"\$i\" ]; then + DEST=\$(realpath \$i/../latest) + echo \"๐Ÿ“ฆ Updating: \$i โ†’ \$DEST\" + rm -rf \"\$DEST\" + mkdir -p \"\$DEST\" + cp -r \"\$i\"/* \"\$DEST/\" + UPDATED_COUNT=\$((UPDATED_COUNT + 1)) + echo \"โœ… Updated: \$DEST\" + fi + done + + if [ \$UPDATED_COUNT -eq 0 ]; then + echo 'โš ๏ธ No packages found for version '\$VERSION + exit 1 + fi + + echo \"\" + echo \"๐ŸŽ‰ Successfully updated \$UPDATED_COUNT package(s) to latest\" + " + + - name: Verify updates + run: | + ssh -o StrictHostKeyChecking=no \ + -o UserKnownHostsFile=/dev/null \ + genie.zenoh@projects-storage.eclipse.org \ + " + set -e + BASE_PATH='/home/data/httpd/download.eclipse.org/zenoh' + + echo '๐Ÿ” Verifying latest directories...' + for latest_dir in \$BASE_PATH/z*/latest; do + if [ -d \"\$latest_dir\" ]; then + FILE_COUNT=\$(find \"\$latest_dir\" -type f | wc -l) + echo \" โœ… \$latest_dir (\$FILE_COUNT files)\" + fi + done + " + + - name: Report completion + if: always() + run: | + echo "Update Latest Downloads Workflow Completed" + echo "Version: ${{ inputs.version }}" + echo "Timestamp: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" diff --git a/README.md b/README.md index 32f1a3dd..6024d780 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,47 @@ This repository contains a set of GitHub actions and (reusable) workflows used to implement cross-repository workflows and reuse workflows across the eclipse-zenoh organization. + +## Workflows + +### update-latest-downloads.yml + +**Purpose**: Update the "latest" symlink on download.eclipse.org to point to a specific release version. + +**Trigger**: Manual (`workflow_dispatch`) + +**Inputs**: +- `version` (required): The version to mark as latest (e.g., `1.7.2`) + +**Required Secrets**: +- `SSH_PRIVATE_KEY`: SSH private key (ED25519) for `genie.zenoh` authentication +- `SSH_PASSPHRASE`: Passphrase for the SSH key (if key is encrypted) + +**Setup**: +Request SCP credentials from Eclipse CBI by opening a [HelpDesk issue](https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/issues/new) with the following: +- Project: Zenoh +- Request: SSH credentials for `projects-storage.eclipse.org` +- Purpose: Automated downloads.eclipse.org management + +Once credentials are provided, add them as GitHub Secrets: +1. Navigate to Settings โ†’ Secrets and variables โ†’ Actions +2. Create the four secrets listed above +3. Alternatively, add via [Otterdog configuration](https://github.com/eclipse-cbi/.eclipsefdn) + +**Behavior**: +1. Connects to `projects-storage.eclipse.org` via SSH +2. For each package directory matching `/home/data/httpd/download.eclipse.org/zenoh/z*/{version}/`: + - Copies all files to the corresponding `latest/` directory + - Removes old `latest/` directory before copying + - Creates `latest/` if it doesn't exist +3. Reports the number of packages updated +4. Verifies all `latest/` directories contain files + +**Example**: +To update latest downloads for version 1.7.2: +1. Navigate to Actions โ†’ Update latest downloads on download.eclipse.org +2. Click "Run workflow" +3. Enter `1.7.2` in the version field +4. Click "Run workflow" + +The workflow will update all package "latest" directories to mirror the 1.7.2 release artifacts. From 5b29c1d3862e2c1a97006ae019851ef6276e6c20 Mon Sep 17 00:00:00 2001 From: Diogo Mendes Matsubara Date: Mon, 2 Feb 2026 10:17:25 +0100 Subject: [PATCH 2/3] Add dry-run option to update-latest-downloads workflow - Add 'dry-run' boolean input parameter - In dry-run mode: verify SSH connection and list files that would be copied - In live mode: actually copy files to latest directories - Dry-run useful for testing credentials without modifying production - Updated README with dry-run usage instructions --- .github/workflows/update-latest-downloads.yml | 34 +++++++++++++++---- README.md | 25 ++++++++------ 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/.github/workflows/update-latest-downloads.yml b/.github/workflows/update-latest-downloads.yml index aafb2d5a..a1b91ec0 100644 --- a/.github/workflows/update-latest-downloads.yml +++ b/.github/workflows/update-latest-downloads.yml @@ -7,6 +7,11 @@ on: description: 'Version to mark as latest (e.g., 1.7.2)' required: true type: string + dry-run: + description: 'Test mode - verify connections and show what would be updated without modifying' + required: false + type: boolean + default: false jobs: update-latest: @@ -24,6 +29,7 @@ jobs: - name: Update latest symlinks on download.eclipse.org run: | + DRY_RUN="${{ inputs.dry-run }}" ssh -o StrictHostKeyChecking=no \ -o UserKnownHostsFile=/dev/null \ genie.zenoh@projects-storage.eclipse.org \ @@ -33,16 +39,28 @@ jobs: BASE_PATH='/home/data/httpd/download.eclipse.org/zenoh' UPDATED_COUNT=0 + if [ \"\$DRY_RUN\" = \"true\" ]; then + echo '๐Ÿงช DRY-RUN MODE - Credentials verified, no changes will be made' + echo '' + fi + echo '๐Ÿ” Scanning for zenoh packages with version \$VERSION...' for i in \$BASE_PATH/z*/\$VERSION; do if [ -d \"\$i\" ]; then DEST=\$(realpath \$i/../latest) - echo \"๐Ÿ“ฆ Updating: \$i โ†’ \$DEST\" - rm -rf \"\$DEST\" - mkdir -p \"\$DEST\" - cp -r \"\$i\"/* \"\$DEST/\" + + if [ \"\$DRY_RUN\" = \"true\" ]; then + FILE_COUNT=\$(find \"\$i\" -type f | wc -l) + echo \"๐Ÿ“ฆ [DRY-RUN] Would update: \$i (\$FILE_COUNT files) โ†’ \$DEST\" + else + echo \"๐Ÿ“ฆ Updating: \$i โ†’ \$DEST\" + rm -rf \"\$DEST\" + mkdir -p \"\$DEST\" + cp -r \"\$i\"/* \"\$DEST/\" + echo \"โœ… Updated: \$DEST\" + fi + UPDATED_COUNT=\$((UPDATED_COUNT + 1)) - echo \"โœ… Updated: \$DEST\" fi done @@ -52,7 +70,11 @@ jobs: fi echo \"\" - echo \"๐ŸŽ‰ Successfully updated \$UPDATED_COUNT package(s) to latest\" + if [ \"\$DRY_RUN\" = \"true\" ]; then + echo \"๐ŸŽ‰ DRY-RUN successful: would update \$UPDATED_COUNT package(s)\" + else + echo \"๐ŸŽ‰ Successfully updated \$UPDATED_COUNT package(s) to latest\" + fi " - name: Verify updates diff --git a/README.md b/README.md index 6024d780..fb7f7264 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ eclipse-zenoh organization. **Inputs**: - `version` (required): The version to mark as latest (e.g., `1.7.2`) +- `dry-run` (optional): Test mode - verify credentials and show what would be updated without modifying (default: `false`) **Required Secrets**: - `SSH_PRIVATE_KEY`: SSH private key (ED25519) for `genie.zenoh` authentication @@ -33,17 +34,19 @@ Once credentials are provided, add them as GitHub Secrets: **Behavior**: 1. Connects to `projects-storage.eclipse.org` via SSH 2. For each package directory matching `/home/data/httpd/download.eclipse.org/zenoh/z*/{version}/`: - - Copies all files to the corresponding `latest/` directory - - Removes old `latest/` directory before copying - - Creates `latest/` if it doesn't exist -3. Reports the number of packages updated -4. Verifies all `latest/` directories contain files - -**Example**: -To update latest downloads for version 1.7.2: + - **Dry-run mode**: Lists files that would be copied without making changes + - **Live mode**: Copies all files to the corresponding `latest/` directory, removing old `latest/` first +3. Reports the number of packages updated/would be updated +4. In dry-run: Verifies SSH connection and credentials work +5. In live: Verifies all `latest/` directories contain files + +**Usage**: +First-time setup: Use `dry-run: true` to verify credentials: 1. Navigate to Actions โ†’ Update latest downloads on download.eclipse.org 2. Click "Run workflow" -3. Enter `1.7.2` in the version field -4. Click "Run workflow" +3. Enter the version (e.g., `1.7.2`) +4. Check `dry-run` checkbox +5. Click "Run workflow" +6. Workflow will connect and show what would be updated without making changes -The workflow will update all package "latest" directories to mirror the 1.7.2 release artifacts. +Production run: Once dry-run succeeds, run again with `dry-run: false` to actually update files. From e62d480611b1422eec1ab5d906791e0d6c67b461 Mon Sep 17 00:00:00 2001 From: Diogo Mendes Matsubara Date: Mon, 2 Feb 2026 10:33:57 +0100 Subject: [PATCH 3/3] Convert to symlink-based approach for latest downloads - Changed from cp -r (file copy) to ln -sfr (symlinks) - More space-efficient: 'latest' symlinks directly to version directory - Faster: only symlink creation instead of copying large file trees - Verification step now checks symlink targets instead of file counts - Dry-run shows what symlinks would be created - Updated README documentation --- .github/workflows/update-latest-downloads.yml | 24 +++++++++---------- README.md | 11 +++++---- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/.github/workflows/update-latest-downloads.yml b/.github/workflows/update-latest-downloads.yml index a1b91ec0..d1e389db 100644 --- a/.github/workflows/update-latest-downloads.yml +++ b/.github/workflows/update-latest-downloads.yml @@ -50,14 +50,12 @@ jobs: DEST=\$(realpath \$i/../latest) if [ \"\$DRY_RUN\" = \"true\" ]; then - FILE_COUNT=\$(find \"\$i\" -type f | wc -l) - echo \"๐Ÿ“ฆ [DRY-RUN] Would update: \$i (\$FILE_COUNT files) โ†’ \$DEST\" + echo \"๐Ÿ”— [DRY-RUN] Would create symlink: \$DEST โ†’ \$i\" else - echo \"๐Ÿ“ฆ Updating: \$i โ†’ \$DEST\" + echo \"๐Ÿ”— Creating symlink: \$DEST โ†’ \$i\" rm -rf \"\$DEST\" - mkdir -p \"\$DEST\" - cp -r \"\$i\"/* \"\$DEST/\" - echo \"โœ… Updated: \$DEST\" + ln -sfr \"\$i\" \"\$DEST\" + echo \"โœ… Symlink created: \$DEST\" fi UPDATED_COUNT=\$((UPDATED_COUNT + 1)) @@ -71,9 +69,9 @@ jobs: echo \"\" if [ \"\$DRY_RUN\" = \"true\" ]; then - echo \"๐ŸŽ‰ DRY-RUN successful: would update \$UPDATED_COUNT package(s)\" + echo \"๐ŸŽ‰ DRY-RUN successful: would create \$UPDATED_COUNT symlink(s)\" else - echo \"๐ŸŽ‰ Successfully updated \$UPDATED_COUNT package(s) to latest\" + echo \"๐ŸŽ‰ Successfully created \$UPDATED_COUNT symlink(s) to latest\" fi " @@ -86,11 +84,11 @@ jobs: set -e BASE_PATH='/home/data/httpd/download.eclipse.org/zenoh' - echo '๐Ÿ” Verifying latest directories...' - for latest_dir in \$BASE_PATH/z*/latest; do - if [ -d \"\$latest_dir\" ]; then - FILE_COUNT=\$(find \"\$latest_dir\" -type f | wc -l) - echo \" โœ… \$latest_dir (\$FILE_COUNT files)\" + echo '๐Ÿ” Verifying latest symlinks...' + for latest_link in \$BASE_PATH/z*/latest; do + if [ -L \"\$latest_link\" ]; then + TARGET=\$(readlink \"\$latest_link\") + echo \" โœ… \$latest_link โ†’ \$TARGET\" fi done " diff --git a/README.md b/README.md index fb7f7264..93501a4a 100644 --- a/README.md +++ b/README.md @@ -34,11 +34,12 @@ Once credentials are provided, add them as GitHub Secrets: **Behavior**: 1. Connects to `projects-storage.eclipse.org` via SSH 2. For each package directory matching `/home/data/httpd/download.eclipse.org/zenoh/z*/{version}/`: - - **Dry-run mode**: Lists files that would be copied without making changes - - **Live mode**: Copies all files to the corresponding `latest/` directory, removing old `latest/` first -3. Reports the number of packages updated/would be updated -4. In dry-run: Verifies SSH connection and credentials work -5. In live: Verifies all `latest/` directories contain files + - **Dry-run mode**: Lists symlinks that would be created without making changes + - **Live mode**: Creates symlinks from `latest/` to the version directory (removes old symlinks first) +3. Symlinks are force-created with `ln -sfr` (space-efficient, points to actual version directory) +4. Reports the number of symlinks created/would be created +5. In dry-run: Verifies SSH connection and credentials work +6. In live: Verifies all `latest/` symlinks point to correct version directories **Usage**: First-time setup: Use `dry-run: true` to verify credentials: