diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml new file mode 100644 index 0000000..4284684 --- /dev/null +++ b/.github/actions/build/action.yml @@ -0,0 +1,120 @@ +name: 'Build Redis Snap' +description: 'Build Redis snap package with configurable version' +inputs: + version: + description: 'Redis version to build (e.g., "unstable", "8.4-rc1", or a tag like "7.2.4")' + required: true + architecture: + description: 'Architecture to build for (amd64 or arm64)' + required: true +outputs: + packages_list: + description: 'JSON list of built snap files' + value: ${{ steps.list-packages.outputs.packages_list }} + +runs: + using: 'composite' + steps: + - name: Checkout Redis repository + uses: actions/checkout@v4 + with: + repository: redis/redis + path: redis + ref: ${{ inputs.version }} + + - name: Configure Redis modules to use master + if: inputs.version == 'unstable' + shell: bash + run: | + echo "Updating module versions to use master branch" + for module in redisbloom redisearch redistimeseries redisjson; do + if [ -f "redis/modules/${module}/Makefile" ]; then + echo "Updating ${module} to use master branch" + sed -i 's/MODULE_VERSION = .*/MODULE_VERSION = master/' "redis/modules/${module}/Makefile" + echo "Verifying ${module} version: $(grep "MODULE_VERSION" "redis/modules/${module}/Makefile")" + fi + done + + - name: Setup Snapcraft + shell: bash + run: | + sudo snap install snapcraft --classic + + - name: Setup LXD + uses: canonical/setup-lxd@v0.1.2 + + - name: Build Snap + shell: bash + env: + SNAPCRAFT_BUILD_INFO: 1 + run: | + sudo snapcraft + + - name: List built packages + id: list-packages + shell: bash + run: | + packages=$(ls *.snap | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "packages_list=$packages" >> $GITHUB_OUTPUT + echo "Built packages: $packages" + + - name: Upload to artifacts + uses: actions/upload-artifact@v4 + with: + name: redis-snap-${{ inputs.architecture }}-${{ github.sha }} + path: '*.snap' + retention-days: 1 + + - name: Capture build logs on failure + if: failure() && inputs.version == 'unstable' + shell: bash + run: | + mkdir -p /tmp/build-logs + + echo "Build failed for snap on ${{ inputs.architecture }}" + echo "Capturing detailed logs for troubleshooting..." + + # Get system info + uname -a > /tmp/build-logs/system-info.log 2>&1 + snap --version > /tmp/build-logs/snap-info.log 2>&1 + snapcraft --version >> /tmp/build-logs/snap-info.log 2>&1 + + # Get LXD container info + lxc list > /tmp/build-logs/lxc-list.log 2>&1 || echo "Failed to list LXC containers" + lxc info > /tmp/build-logs/lxc-info.log 2>&1 || echo "Failed to get LXC info" + + # Get snap environment info + snap list > /tmp/build-logs/snap-list.log 2>&1 + + # Get Redis source info + if [ -d "redis" ]; then + (cd redis && git log -n 3) > /tmp/build-logs/redis-git-info.log 2>&1 + find redis/modules -name "Makefile" -exec grep "MODULE_VERSION" {} \; > /tmp/build-logs/module-versions.log 2>&1 + fi + + # Get snap parts info if they exist + if [ -d "parts" ]; then + find parts -name "*.log" -exec cp {} /tmp/build-logs/ \; || echo "No part logs found" + find parts -type f -name "*.log" | sort > /tmp/build-logs/parts-logs-list.txt 2>&1 + fi + + # Create a summary file + { + echo "Build failure summary for snap on ${{ inputs.architecture }}" + echo "Date: $(date)" + echo "GitHub SHA: ${{ github.sha }}" + echo "Architecture: ${{ inputs.architecture }}" + echo "Version: ${{ inputs.version }}" + } > /tmp/build-logs/failure-summary.txt + + echo "Log capture complete" + + - name: Upload build failure logs + if: failure() && inputs.version == 'unstable' + uses: actions/upload-artifact@v4 + with: + name: build-failure-${{ inputs.architecture }}-snap + path: /tmp/build-logs/ + retention-days: 30 + if-no-files-found: warn + diff --git a/.github/actions/common/slack.sh b/.github/actions/common/slack.sh new file mode 100644 index 0000000..7c68f76 --- /dev/null +++ b/.github/actions/common/slack.sh @@ -0,0 +1,151 @@ +#!/bin/bash + + +# Send a Slack message using Bot Token API +# Reads JSON message from stdin, sends to Slack API +# Usage: slack_send_with_token "$SLACK_BOT_TOKEN" < message.json +slack_send_with_token() { + set -x + local token="$1" + local curl_stderr=$(mktemp) + + # Run curl with verbose output, stderr to curl_stderr + if ! curl --fail-with-body -v -X POST https://api.slack.com/api/chat.postMessage \ + -H "Authorization: Bearer $token" \ + -H "Content-Type: application/json" \ + -d @- 2>"$curl_stderr"; then + # If curl failed, output the error log + echo "curl command failed. Error log:" >&2 + cat "$curl_stderr" >&2 + rm -f "$curl_stderr" + return 1 + fi + + rm -f "$curl_stderr" + return 0 +} + +# Handle Slack API response and extract message metadata +# Reads JSON response from stdin +# If GITHUB_OUTPUT is set, writes slack_ts and slack_url to it +# Usage: slack_handle_message_result "$SLACK_CHANNEL_ID" < response.json +slack_handle_message_result() { + set -x + local channel_id="$1" + local message="$2" + local response=$(cat) + + echo "Slack API Response:" + + # Check if successful + if echo "$response" | jq -e '.ok == true' > /dev/null; then + local slack_ts=$(echo "$response" | jq -r '.ts') + local slack_channel=$(echo "$response" | jq -r '.channel') + + # Convert timestamp to URL format (remove dot) + local ts_for_url=$(echo "$slack_ts" | tr -d '.') + local slack_url="https://redis.slack.com/archives/${slack_channel}/p${ts_for_url}" + + # Write to GITHUB_OUTPUT if available + if [ -n "$GITHUB_OUTPUT" ]; then + echo "slack_ts=$slack_ts" >> "$GITHUB_OUTPUT" + echo "slack_url=$slack_url" >> "$GITHUB_OUTPUT" + fi + + echo "✅ Message sent successfully!" + echo "Message URL: $slack_url" + return 0 + else + local error=$(echo "$response" | jq -r '.error // "unknown"') + echo "❌ Failed to send Slack message: $error" >&2 + echo "$response" | jq '.' + echo "Message content: $message" >&2 + return 1 + fi +} + +slack_format_success_message() { +jq --arg channel "$1" --arg release_tag "$2" --arg footer "$3" --arg env "$4" ' +{ + "channel": $channel, + "icon_emoji": ":redis-circle:", + "text": (":ubuntu: SNAP Packages Published for Redis: " + $release_tag + " (" + $env + ")"), + "blocks": ( + [ + { + "type": "header", + "text": { "type": "plain_text", "text": (":ubuntu: SNAP Packages Published for Release " + $release_tag + " (" + $env + ")") } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "The following packages have been published to https://snapcraft.io/redis" + } + } + ] + + map({ + "type": "section", + "text": { + "type": "mrkdwn", + "text": ("*" + .file + "* (revision: " + .revision + ")") + } + }) + + [ + { + "type": "context", + "elements": [ + { "type": "mrkdwn", "text": $footer } + ] + } + ] + ) +}' +} + +slack_format_failure_message() { + channel=$1 + header=$2 + workflow_url=$3 + footer=$4 + if [ -z "$header" ]; then + header=" " + fi + if [ -z "$footer" ]; then + footer=" " + fi + +# Create Slack message payload + cat << EOF +{ +"channel": "$channel", +"icon_emoji": ":redis-circle:", +"text": "$header", +"blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "❌ $header" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Workflow run: $workflow_url" + } + }, + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": "$footer" + } + ] + } +] +} +EOF +} diff --git a/.github/actions/determine-version/action.yml b/.github/actions/determine-version/action.yml new file mode 100644 index 0000000..caf8305 --- /dev/null +++ b/.github/actions/determine-version/action.yml @@ -0,0 +1,47 @@ +name: 'Determine Redis Version' +description: 'Determine Redis version to build based on risk level from .redis_versions.json' +inputs: + risk_level: + description: 'Risk level (edge, candidate, stable)' + required: true + +outputs: + redis_version: + description: 'Redis version to build (e.g., "8.4.0", "unstable")' + value: ${{ steps.determine-version.outputs.redis_version }} + +runs: + using: 'composite' + steps: + - name: Validate risk level + shell: bash + run: | + if [[ ! "${{ inputs.risk_level }}" =~ ^(edge|candidate|stable)$ ]]; then + echo "Error: risk_level must be one of: edge, candidate, stable" + echo "Provided value: ${{ inputs.risk_level }}" + exit 1 + fi + echo "Risk level validation passed: ${{ inputs.risk_level }}" + + - name: Determine Redis version from risk level + id: determine-version + shell: bash + run: | + if [ ! -f ".redis_versions.json" ]; then + echo "Error: .redis_versions.json not found" + exit 1 + fi + + REDIS_VERSION=$(jq -r ".${{ inputs.risk_level }}" .redis_versions.json) + + if [ "$REDIS_VERSION" = "null" ] || [ -z "$REDIS_VERSION" ]; then + echo "Error: Risk level '${{ inputs.risk_level }}' not found in .redis_versions.json" + echo "Available risk levels:" + jq -r 'keys[]' .redis_versions.json + exit 1 + fi + + echo "Risk level: ${{ inputs.risk_level }}" + echo "Redis version: $REDIS_VERSION" + echo "redis_version=$REDIS_VERSION" >> $GITHUB_OUTPUT + diff --git a/.github/actions/run-tests/action.yml b/.github/actions/run-tests/action.yml new file mode 100644 index 0000000..efff98d --- /dev/null +++ b/.github/actions/run-tests/action.yml @@ -0,0 +1,179 @@ +name: 'Run Redis Snap Tests' +description: 'Run comprehensive tests against Redis snap package' +inputs: + architecture: + description: 'Architecture of the snap to test (amd64 or arm64)' + required: true + os: + description: 'OS version being tested (e.g., ubuntu-22.04, ubuntu-24.04)' + required: true + run_id: + description: 'GitHub Actions run ID to download artifacts from (optional, defaults to current run)' + required: false + default: '' + github_token: + description: 'GitHub token for downloading artifacts from another run (optional)' + required: false + default: '' + +runs: + using: 'composite' + steps: + - name: Setup test environment + shell: bash + run: | + echo "Testing on ${{ inputs.os }} for ${{ inputs.architecture }}" + echo "System information:" + uname -a + lsb_release -a + + - name: Download artifact from current run + if: inputs.run_id == '' + uses: actions/download-artifact@v4 + with: + name: redis-snap-${{ inputs.architecture }}-${{ github.sha }} + path: ./snap-artifacts + + - name: Download artifact from specific run + if: inputs.run_id != '' + uses: actions/download-artifact@v4 + with: + name: redis-snap-${{ inputs.architecture }}-${{ github.sha }} + path: ./snap-artifacts + run-id: ${{ inputs.run_id }} + github-token: ${{ inputs.github_token }} + + - name: Verify artifacts + shell: bash + run: | + ls -la ./snap-artifacts + echo "Found snap files:" + find ./snap-artifacts -name "*.snap" + + - name: Install Redis snap package + shell: bash + run: | + SNAP_FILE=$(ls snap-artifacts/*.snap) + echo "Installing snap: $SNAP_FILE" + sudo snap install --dangerous $SNAP_FILE + + - name: Prepare config test + shell: bash + run: | + sudo sed -i 's/dump.rdb/dump-preconfigured.rdb/g' /var/snap/redis/common/etc/redis/redis.conf + + - name: Verify Redis installation and start Redis + shell: bash + run: | + snap list | grep redis + snap services | grep redis || echo "Redis service not found." + # service is started by default on install, but we need to reapply updated config + sudo snap restart redis.server + + - name: Basic Sanity Tests + shell: bash + run: | + for i in {1..5}; do redis.cli ping &>/dev/null && break || echo "Waiting for Redis... $i" && sleep 1; done + redis.cli info server || { echo "Cannot get server info"; exit 1; } + + - name: Configuration Tests + shell: bash + run: | + [ "$(redis.cli CONFIG GET dbfilename | tail -1 )" = "dump-preconfigured.rdb" ] || \ + { echo "Configuration test failed: + expected: 'dump-preconfigured.rdb' + got : '$(redis.cli CONFIG GET dbfilename)'"; exit 1; } + # dbfilename is immutable, so use something else that won't become a default + redis.cli CONFIG SET tls-protocols "TLSv1.2" + redis.cli CONFIG REWRITE + grep 'tls-protocols "TLSv1.2"' /var/snap/redis/common/etc/redis/redis.conf || \ + { echo "Configuration REWRITE test failed: + expected: 'tls-protocols \"TLSv1.2\"' + got : '$(grep tls-protocols /var/snap/redis/common/etc/redis/redis.conf)'"; exit 1; } + + - name: Verify installed modules + shell: bash + run: | + modules=$(redis.cli module list) + echo "Installed modules:" + echo "$modules" + missing_modules=() + for module in "bf" "search" "timeseries" "ReJSON"; do + if ! echo "$modules" | grep -q "$module"; then + missing_modules+=("$module") + fi + done + if [ ${#missing_modules[@]} -eq 0 ]; then + echo "All required modules are installed" + else + echo "The following modules are missing: ${missing_modules[*]}" + exit 1 + fi + + - name: Test RedisBloom + shell: bash + run: | + redis.cli BF.ADD popular_keys "redis:hash" + redis.cli BF.ADD popular_keys "redis:set" + [ "$(redis.cli BF.EXISTS popular_keys "redis:hash")" = "1" ] || \ + { echo "RedisBloom test failed: 'redis:hash' not found"; exit 1; } + [ "$(redis.cli BF.EXISTS popular_keys "redis:list")" = "0" ] || \ + { echo "RedisBloom test failed: 'redis:list' found unexpectedly"; exit 1; } + echo "RedisBloom test passed successfully" + + - name: Test RediSearch + shell: bash + run: | + redis.cli FT.CREATE redis_commands ON HASH PREFIX 1 cmd: SCHEMA name TEXT SORTABLE description TEXT + redis.cli HSET cmd:set name "SET" description "Set the string value of a key" + redis.cli HSET cmd:get name "GET" description "Get the value of a key" + result=$(redis.cli FT.SEARCH redis_commands "value") + if echo "$result" | grep -q "Set the string value of a key" && \ + echo "$result" | grep -q "Get the value of a key"; then + echo "RediSearch test passed successfully" + else + echo "RediSearch test failed: expected commands not found in search results" + exit 1 + fi + + - name: Test RedisTimeSeries + shell: bash + run: | + redis.cli TS.CREATE redis:cpu:usage RETENTION 86400 + redis.cli TS.ADD redis:cpu:usage "*" 80 + redis.cli TS.ADD redis:cpu:usage "*" 65 + redis.cli TS.ADD redis:cpu:usage "*" 70 + result=$(redis.cli TS.RANGE redis:cpu:usage - + COUNT 3) + if echo "$result" | grep -q "80" && \ + echo "$result" | grep -q "65" && \ + echo "$result" | grep -q "70"; then + echo "RedisTimeSeries test passed successfully" + else + echo "RedisTimeSeries test failed: expected values not found in time series" + exit 1 + fi + + - name: Test ReJSON + shell: bash + run: | + redis.cli JSON.SET redis:config $ '{"maxmemory":"2gb","maxmemory-policy":"allkeys-lru"}' + result=$(redis.cli JSON.GET redis:config $.maxmemory-policy) + cleaned_result=$(echo $result | tr -d '[]"') + if [ "$cleaned_result" = "allkeys-lru" ]; then + echo "ReJSON test passed successfully" + else + echo "ReJSON test failed: expected 'allkeys-lru', got $result" + exit 1 + fi + + - name: Check Redis snap status + shell: bash + run: | + snap info redis + + - name: Cleanup + if: always() + shell: bash + run: | + sudo snap remove redis || true + diff --git a/.github/actions/slack-notification/action.yml b/.github/actions/slack-notification/action.yml new file mode 100644 index 0000000..cdd115c --- /dev/null +++ b/.github/actions/slack-notification/action.yml @@ -0,0 +1,107 @@ +inputs: + slack_func: + description: 'Slack message format function to use' + required: true + slack_channel_id: + description: 'Slack channel ID to post to' + required: true + release_tag: + description: 'Release tag to build' + required: true + url_prefix: + description: 'Prefix to add to package URLs (not used for SNAP packages)' + required: false + env: + description: 'Packages target s3 environment' + required: true + snap_upload_info: + description: 'JSON structure of uploaded packages by distribution and architecture' + required: true + message: + description: 'Message to send in case of failure' + required: false + SLACK_BOT_TOKEN: + description: 'Slack bot token for API authentication' + required: true + +outputs: + slack_ts: + description: 'Slack message timestamp' + value: ${{ steps.send-success.outputs.slack_ts || steps.send-failure.outputs.slack_ts }} + slack_url: + description: 'URL to the Slack message' + value: ${{ steps.send-success.outputs.slack_url || steps.send-failure.outputs.slack_url }} + +runs: + using: "composite" + steps: + - name: Send Slack notification + id: send-success + if: inputs.slack_func == 'slack_format_success_message' + shell: bash + env: + SLACK_BOT_TOKEN: ${{ inputs.SLACK_BOT_TOKEN }} + run: | + set -e + workflow_url="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + footer="Repository: ${{ github.repository }} | Commit: \`${{ github.sha }}\` | View: <$workflow_url|workflow run>" + + . ${{ github.action_path }}/../common/slack.sh + + # Generate message + msgfile=$(mktemp) + cat <<'JSON' | slack_format_success_message \ + "${{ inputs.slack_channel_id }}" "${{ inputs.release_tag }}" "$footer" "${{ inputs.env }}" \ + > "$msgfile" + ${{ inputs.snap_upload_info }} + JSON + + # Send message + send_result=$(mktemp) + if ! slack_send_with_token "$SLACK_BOT_TOKEN" < "$msgfile" > "$send_result"; then + echo " Error sending message:" + cat "$msgfile" + exit 1 + fi + + # Handle result + slack_handle_message_result "${{ inputs.slack_channel_id }}" "$(cat "$msgfile")" < "$send_result" + + - name: Send Failure Slack notification + id: send-failure + if: inputs.slack_func == 'slack_format_failure_message' + shell: bash + env: + SLACK_BOT_TOKEN: ${{ inputs.SLACK_BOT_TOKEN }} + run: | + set -e + workflow_url="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + footer="Repository: ${{ github.repository }} | Commit: \`${{ github.sha }}\`" + + msg='${{ inputs.message }}' + if [ -z "$msg" ]; then + echo "Error: message is required" + exit 1 + fi + + . ${{ github.action_path }}/../common/slack.sh + + # Generate message + msgfile=$(mktemp) + slack_format_failure_message \ + "${{ inputs.slack_channel_id }}" \ + "$msg for Redis: ${{ inputs.release_tag || 'unknown'}} (${{ inputs.env }})" \ + "$workflow_url" \ + "$footer" \ + > "$msgfile" + + # Send message + send_result=$(mktemp) + if ! slack_send_with_token "$SLACK_BOT_TOKEN" < "$msgfile" > "$send_result"; then + echo "Error sending message:" + cat "$msgfile" + exit 1 + fi + + # Handle result + slack_handle_message_result "${{ inputs.slack_channel_id }}" "$(cat "$msgfile")" < "$send_result" \ No newline at end of file diff --git a/.github/actions/update-redis-versions/action.yml b/.github/actions/update-redis-versions/action.yml new file mode 100644 index 0000000..6628fdb --- /dev/null +++ b/.github/actions/update-redis-versions/action.yml @@ -0,0 +1,35 @@ +name: 'Update Redis Versions' +description: 'Update .redis_versions.json with new release tag for specified risk level' +inputs: + risk_level: + description: 'Risk level to update (stable, candidate)' + required: true + release_tag: + description: 'Release tag to set for the risk level' + required: true + release_version_branch: + description: 'Release version branch to commit to' + required: true + +outputs: + changed_files: + description: 'List of files that were modified' + value: ${{ steps.update-versions.outputs.changed_files }} + +runs: + using: "composite" + steps: + - name: Update Redis Versions + id: update-versions + shell: bash + run: | + ${{ github.action_path }}/update-redis-versions.sh ${{ inputs.risk_level }} ${{ inputs.release_tag }} + + - name: Create verified commit + if: steps.update-versions.outputs.changed_files != '' + uses: iarekylew00t/verified-bot-commit@v1 + with: + message: "Update ${{ inputs.risk_level }} to ${{ inputs.release_tag }}" + files: ${{ steps.update-versions.outputs.changed_files }} + ref: ${{ inputs.release_version_branch }} + diff --git a/.github/actions/update-redis-versions/update-redis-versions.sh b/.github/actions/update-redis-versions/update-redis-versions.sh new file mode 100755 index 0000000..ac4bc86 --- /dev/null +++ b/.github/actions/update-redis-versions/update-redis-versions.sh @@ -0,0 +1,105 @@ +#!/bin/bash +set -e + +# This script updates .redis_versions.json with the provided risk_level and release_tag +# and commits changes if any were made. + +# Input RISK_LEVEL is expected in $1 +# Input RELEASE_TAG is expected in $2 +RISK_LEVEL="$1" +RELEASE_TAG="$2" + +if [ -z "$RISK_LEVEL" ]; then + echo "Error: RISK_LEVEL is required as first argument" + exit 1 +fi + +if [ -z "$RELEASE_TAG" ]; then + echo "Error: RELEASE_TAG is required as second argument" + exit 1 +fi + +echo "RISK_LEVEL: $RISK_LEVEL" +echo "RELEASE_TAG: $RELEASE_TAG" + +VERSIONS_FILE=".redis_versions.json" + +if [ ! -f "$VERSIONS_FILE" ]; then + echo "Error: $VERSIONS_FILE not found" + exit 1 +fi + +# Validate that the file is valid JSON +if ! jq empty "$VERSIONS_FILE" 2>/dev/null; then + echo "Error: $VERSIONS_FILE is not valid JSON" + exit 1 +fi + +# Check if risk_level exists in the JSON file +if ! jq -e "has(\"$RISK_LEVEL\")" "$VERSIONS_FILE" > /dev/null; then + echo "Error: Risk level '$RISK_LEVEL' does not exist in $VERSIONS_FILE" + echo "Available risk levels:" + jq -r 'keys[]' "$VERSIONS_FILE" + exit 1 +fi + +# Refuse to change "edge" risk level +if [ "$RISK_LEVEL" = "edge" ]; then + echo "Error: Cannot update 'edge' risk level. Edge is reserved for unstable builds." + exit 1 +fi + +# Get current value for this risk level +CURRENT_VALUE=$(jq -r ".$RISK_LEVEL" "$VERSIONS_FILE") +echo "Current value for $RISK_LEVEL: $CURRENT_VALUE" + +# Check if the value is already set to the release tag +if [ "$CURRENT_VALUE" = "$RELEASE_TAG" ]; then + echo "Risk level '$RISK_LEVEL' is already set to '$RELEASE_TAG', no changes needed" + if [ -n "$GITHUB_OUTPUT" ]; then + echo "changed_files=" >> "$GITHUB_OUTPUT" + fi + exit 0 +fi + +# Update the JSON file +echo "Updating $RISK_LEVEL from '$CURRENT_VALUE' to '$RELEASE_TAG'..." +jq ".$RISK_LEVEL = \"$RELEASE_TAG\"" "$VERSIONS_FILE" > "${VERSIONS_FILE}.tmp" +mv "${VERSIONS_FILE}.tmp" "$VERSIONS_FILE" + +# Verify the update was successful +NEW_VALUE=$(jq -r ".$RISK_LEVEL" "$VERSIONS_FILE") +if [ "$NEW_VALUE" != "$RELEASE_TAG" ]; then + echo "Error: Failed to update $VERSIONS_FILE" + exit 1 +fi + +echo "Successfully updated $VERSIONS_FILE" +echo "New content:" +cat "$VERSIONS_FILE" + +# Check what files actually changed in git +mapfile -t changed_files < <(git diff --name-only "$VERSIONS_FILE") + +# Output the list of changed files for GitHub Actions +if [ ${#changed_files[@]} -gt 0 ]; then + echo "Files were modified:" + printf '%s\n' "${changed_files[@]}" + + if [ -n "$GITHUB_OUTPUT" ]; then + # Set GitHub Actions output + changed_files_output=$(printf '%s\n' "${changed_files[@]}") + { + echo "changed_files<> "$GITHUB_OUTPUT" + echo "Changed files output set for next step" + fi +else + echo "No files were modified" + if [ -n "$GITHUB_OUTPUT" ]; then + echo "changed_files=" >> "$GITHUB_OUTPUT" + fi +fi + diff --git a/.github/actions/upload/action.yml b/.github/actions/upload/action.yml new file mode 100644 index 0000000..489dede --- /dev/null +++ b/.github/actions/upload/action.yml @@ -0,0 +1,105 @@ +name: 'Upload Redis Snap to Store' +description: 'Upload Redis snap packages to the Snap Store' +inputs: + run_id: + description: 'GitHub Actions run ID to download artifacts from (optional, defaults to current run)' + required: false + default: '' + github_token: + description: 'GitHub token for downloading artifacts from another run (optional)' + required: false + default: '' + risk_level: + description: 'Risk level for the snap release (edge, candidate, or stable)' + required: true + snapcraft_store_credentials: + description: 'Snapcraft store credentials for authentication' + required: true + +outputs: + upload_info: + description: 'JSON array with upload information for each snap' + value: ${{ steps.upload-snaps.outputs.upload_info }} + +runs: + using: 'composite' + steps: + - name: Validate inputs + shell: bash + run: | + if [[ ! "${{ inputs.risk_level }}" =~ ^(edge|candidate|stable)$ ]]; then + echo "Error: risk_level must be one of: edge, candidate, stable" + echo "Provided value: ${{ inputs.risk_level }}" + exit 1 + fi + echo "Risk level validation passed: ${{ inputs.risk_level }}" + + - name: Download all artifacts from current run + if: inputs.run_id == '' + uses: actions/download-artifact@v4 + with: + pattern: redis-snap-* + path: ./snap-artifacts + merge-multiple: true + + - name: Download all artifacts from specific run + if: inputs.run_id != '' + uses: actions/download-artifact@v4 + with: + pattern: redis-snap-* + path: ./snap-artifacts + run-id: ${{ inputs.run_id }} + github-token: ${{ inputs.github_token }} + merge-multiple: true + + - name: Verify artifacts + shell: bash + run: | + ls -la ./snap-artifacts + echo "Found snap files:" + find ./snap-artifacts -name "*.snap" + + - name: Setup Snapcraft + shell: bash + run: | + sudo snap install snapcraft --classic + + - name: Upload snaps to store + id: upload-snaps + shell: bash + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{ inputs.snapcraft_store_credentials }} + run: | + cd snap-artifacts + upload_info_array="[]" + + for snap_file in *.snap; do + if [ -f "$snap_file" ]; then + echo "Uploading $snap_file to ${{ inputs.risk_level }} channel..." + + # Expected output: "Revision 2196 created for 'redis' and released to 'stable'" + snapcraft upload --release=${{ inputs.risk_level }} "$snap_file" | tee upload_output.txt + upload_output=$(cat upload_output.txt) + + revision=$(echo "$upload_output" | grep -oP 'Revision \K[0-9]+' || echo "unknown") + + # Create JSON object with file and revision + upload_info=$(jq -n \ + --arg file "$snap_file" \ + --arg revision "$revision" \ + '{file: $file, revision: $revision}') + + # Add to array + upload_info_array=$(echo "$upload_info_array" | jq -c --argjson item "$upload_info" '. + [$item]') + + echo "Successfully uploaded: $snap_file (revision: $revision)" + fi + done + + echo "upload_info<> $GITHUB_OUTPUT + echo "$upload_info_array" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + echo "Upload information:" + echo "$upload_info_array" | jq '.' + diff --git a/.github/workflows/build-n-test.yml b/.github/workflows/build-n-test.yml new file mode 100644 index 0000000..58706fc --- /dev/null +++ b/.github/workflows/build-n-test.yml @@ -0,0 +1,106 @@ + +name: Build and Test + +on: + workflow_call: + inputs: + release_tag: + description: 'Release tag to build' + type: string + required: false + +env: + # useful for testing unstable flow with different branches` + UNSTABLE_BRANCH: unstable + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - architecture: amd64 + runner: ubuntu-24.04 + - architecture: arm64 + runner: ubuntu24-arm64-4-16 + + runs-on: ${{ matrix.runner }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ inputs.release_tag == 'unstable' && env.UNSTABLE_BRANCH || '' }} + + - name: Ensure Release Branch + if: inputs.release_tag != '' && inputs.release_tag != 'unstable' + id: ensure-branch + uses: redis-developer/redis-oss-release-automation/.github/actions/ensure-release-branch@main + with: + release_tag: ${{ inputs.release_tag }} + release_branch: ${{ github.ref_name }} + allow_modify: false + gh_token: ${{ secrets.GITHUB_TOKEN }} + release_version_branch_prefix: automation/ + + # By default use stable to determine version when release_tag is not specified + # This is used in PR builds + - name: Determine Redis version from .redis_versions.json + if: inputs.release_tag == '' + id: determine-version + uses: ./.github/actions/determine-version + with: + risk_level: stable + + - name: Build Redis Snap + uses: ./.github/actions/build + with: + version: ${{ inputs.release_tag || steps.determine-version.outputs.redis_version }} + architecture: ${{ matrix.architecture }} + + test: + needs: build + strategy: + fail-fast: false + matrix: + include: + # AMD64 runners + - architecture: amd64 + os: ubuntu-22.04 + runner: ubuntu-22.04 + - architecture: amd64 + os: ubuntu-24.04 + runner: ubuntu-24.04 + + # ARM64 runners + - architecture: arm64 + os: ubuntu-22.04 + runner: ubuntu22-arm64-2-8 + - architecture: arm64 + os: ubuntu-24.04 + runner: ubuntu24-arm64-2-8 + + runs-on: ${{ matrix.runner }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ inputs.release_tag == 'unstable' && env.UNSTABLE_BRANCH || '' }} + + - name: Ensure Release Branch + if: inputs.release_tag != '' && inputs.release_tag != 'unstable' + id: ensure-branch + uses: redis-developer/redis-oss-release-automation/.github/actions/ensure-release-branch@main + with: + release_tag: ${{ inputs.release_tag }} + release_branch: ${{ github.ref_name }} + allow_modify: false + gh_token: ${{ secrets.GITHUB_TOKEN }} + release_version_branch_prefix: automation/ + + - name: Run Redis Snap Tests + uses: ./.github/actions/run-tests + with: + architecture: ${{ matrix.architecture }} + os: ${{ matrix.os }} \ No newline at end of file diff --git a/.github/workflows/nightly-unstable-package.yaml b/.github/workflows/nightly-unstable-package.yaml index a199909..ac31286 100644 --- a/.github/workflows/nightly-unstable-package.yaml +++ b/.github/workflows/nightly-unstable-package.yaml @@ -7,4 +7,5 @@ on: jobs: call-unstable-build: + if: github.repository == 'redis/redis-snap' uses: redis/redis-snap/.github/workflows/unstable.yml@unstable diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000..399e89c --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,16 @@ +name: Pull Request Build and Test + +on: + pull_request: + branches: + - master + - unstable + +jobs: + # TODO: we should have a way to run in unstable mode for PRs to unstable but + # without switching to unstable branch + build-and-test: + name: Build and Test + uses: ./.github/workflows/build-n-test.yml + with: + release_tag: \ No newline at end of file diff --git a/.github/workflows/release_build_and_test.yml b/.github/workflows/release_build_and_test.yml new file mode 100644 index 0000000..51c7483 --- /dev/null +++ b/.github/workflows/release_build_and_test.yml @@ -0,0 +1,120 @@ +# This workflow is part of the Redis OSS release automation process. +# In addition to regular tag builds, it also supports building unstable version. +# Unstable release_handle artifact could be used to publish unstable build to +# edge channel with the help of release_publish workflow. +name: Release Build and Test + +on: + workflow_dispatch: + inputs: + release_tag: + description: 'Release tag to build' + required: true + workflow_uuid: + description: 'Optional UUID to identify this workflow run' + required: false + release_type: + description: 'Type of release to upload (public, internal)' + required: true + risk_level: + description: 'Type of stability (stable, rc)' + required: true + +# UUID is used to help automation to identify workflow run in the list of workflow runs. +run-name: "Release Build and Test${{ github.event.inputs.workflow_uuid && format(': {0}', github.event.inputs.workflow_uuid) || '' }}" + +jobs: + prepare-release: + runs-on: ["ubuntu-latest"] + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.release_tag == 'unstable' && 'unstable' || '' }} + + # Note this is for validation only. The git checkout redis/redis is used in the build process. + - name: Validate Redis Release Archive + if: github.event.inputs.release_tag != 'unstable' + uses: redis-developer/redis-oss-release-automation/.github/actions/validate-redis-release-archive@main + with: + release_tag: ${{ github.event.inputs.release_tag }} + + - name: Ensure Release Branch + id: ensure-branch + if: github.event.inputs.release_tag != 'unstable' + uses: redis-developer/redis-oss-release-automation/.github/actions/ensure-release-branch@main + with: + release_tag: ${{ github.event.inputs.release_tag }} + release_branch: ${{ github.ref_name }} + allow_modify: true + gh_token: ${{ secrets.GITHUB_TOKEN }} + release_version_branch_prefix: automation/ + + - name: Update Redis Versions + if: github.event.inputs.release_tag != 'unstable' + uses: ./.github/actions/update-redis-versions + with: + risk_level: ${{ github.event.inputs.risk_level }} + release_tag: ${{ github.event.inputs.release_tag }} + release_version_branch: ${{ steps.ensure-branch.outputs.release_version_branch }} + + build-n-test: + needs: prepare-release + uses: ./.github/workflows/build-n-test.yml + with: + release_tag: ${{ github.event.inputs.release_tag }} + secrets: inherit + + create-release-handle: + needs: build-n-test + runs-on: ubuntu-latest + steps: + - name: Create Release Handle + shell: bash + run: | + cat <result.json + { + "release_tag": "${{ github.event.inputs.release_tag }}", + "risk_level": "${{ github.event.inputs.risk_level }}", + "run_id": ${{ github.run_id }}, + "workflow_uuid": "${{ github.event.inputs.workflow_uuid }}", + "release_type": "${{ github.event.inputs.release_type }}" + } + RELEASE_HANDLE + + - name: Upload release handle artifact + uses: actions/upload-artifact@v4 + with: + name: release_handle + path: result.json + retention-days: 90 + + # Notify only about build failures + # as publish workflow will notify about publish success or failure + slack-failure-notification: + needs: build-n-test + runs-on: ubuntu-latest + if: failure() + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Detect env name + id: detect-env + run: | + if [ "${{ inputs.release_type }}" = "public" ]; then + env_name="production" + elif [ "${{ inputs.release_type }}" = "internal" ]; then + env_name="staging" + fi + echo "env_name=$env_name" >> $GITHUB_OUTPUT + + - name: Send Failure Slack notification + uses: ./.github/actions/slack-notification + with: + slack_func: slack_format_failure_message + slack_channel_id: ${{ vars.SLACK_CHANNEL_ID }} + release_tag: ${{ github.event.inputs.release_tag }} + env: ${{ steps.detect-env.outputs.env_name }} + message: ":ubuntu: SNAP package build failed" + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release_publish.yml b/.github/workflows/release_publish.yml new file mode 100644 index 0000000..6809583 --- /dev/null +++ b/.github/workflows/release_publish.yml @@ -0,0 +1,154 @@ +# This workflow is part of the Redis OSS release automation process. +# In addition to regular tag builds, it also supports publishing unstable builds. +on: + workflow_dispatch: + inputs: + release_tag: + description: 'Release tag to build' + required: true + release_type: + description: 'Type of release to upload (public, internal)' + required: true + workflow_uuid: + description: 'Optional UUID to identify this workflow run' + required: false + release_handle: + description: 'JSON string containing release handle information' + required: true + risk_level: + description: 'Risk level for the release (edge, candidate, stable)' + required: true + +# UUID is used to help automation to identify workflow run in the list of workflow runs. +run-name: "Release Publish${{ github.event.inputs.workflow_uuid && format(': {0}', github.event.inputs.workflow_uuid) || '' }}" + +jobs: + upload-packages: + runs-on: ubuntu-latest + permissions: + # to merge changes into release + contents: write + # to download artifacts from build workflow + actions: read + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Validate inputs + id: validate-inputs + run: | + if [ "${{ inputs.release_type }}" != "public" ]; then + echo "Invalid release_type: ${{ inputs.release_type }}" + exit 1 + fi + env_name="production" + echo "env_name=$env_name" >> $GITHUB_OUTPUT + + - name: Ensure Release Branch + if: github.event.inputs.release_tag != 'unstable' + id: ensure-branch + uses: redis-developer/redis-oss-release-automation/.github/actions/ensure-release-branch@main + with: + release_tag: ${{ github.event.inputs.release_tag }} + release_branch: ${{ github.ref_name }} + allow_modify: false + gh_token: ${{ secrets.GITHUB_TOKEN }} + release_version_branch_prefix: automation/ + + - name: Parse release handle + id: parse-handle + uses: redis-developer/redis-oss-release-automation//.github/actions/parse-release-handle@main + with: + release_handle: ${{ github.event.inputs.release_handle }} + + - name: Upload packages + id: upload + uses: ./.github/actions/upload + with: + run_id: ${{ steps.parse-handle.outputs.run_id }} + github_token: ${{ secrets.GITHUB_TOKEN }} + risk_level: ${{ inputs.risk_level }} + snapcraft_store_credentials: ${{ secrets.SNAP_TOKEN }} + + - name: Merge back to release branch + if: github.event.inputs.release_tag != 'unstable' && github.event.inputs.release_type == 'public' + id: merge-back + # merge only public releases into main + uses: redis-developer/redis-oss-release-automation/.github/actions/merge-branches-verified@main + with: + from_branch: ${{ steps.ensure-branch.outputs.release_version_branch }} + to_branch: ${{ steps.ensure-branch.outputs.release_branch }} + gh_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create version tag + uses: redis-developer/redis-oss-release-automation/.github/actions/create-tag-verified@main + if: steps.merge-back.outputs.merge_commit_sha != '' + with: + tag: v${{ inputs.release_tag }} + ref: ${{ steps.merge-back.outputs.merge_commit_sha }} + gh_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Release info + id: create-release-info + shell: bash + run: | + cat < jq + { + release_tag: "${{ github.event.inputs.release_tag }}", + release_type: "${{ github.event.inputs.release_type }}", + run_id: ${{ github.run_id }}, + packages: . + } + JQ + cat <result.json + ${{ steps.upload.outputs.upload_info }} + RESULT + + - name: Send Success Slack notification + id: slack-success + uses: ./.github/actions/slack-notification + with: + slack_func: slack_format_success_message + slack_channel_id: ${{ vars.SLACK_CHANNEL_ID }} + release_tag: ${{ github.event.inputs.release_tag }} + env: ${{ steps.validate-inputs.outputs.env_name }} + snap_upload_info: ${{ steps.upload.outputs.upload_info }} + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + + - name: Add Slack notification info to release info + if: always() && steps.create-release-info.outcome == 'success' && steps.slack-success.outputs.slack_ts != '' + shell: bash + run: | + # Add Slack notification details to result.json + jq --arg slack_ts "${{ steps.slack-success.outputs.slack_ts }}" \ + --arg slack_channel_id "${{ secrets.SLACK_CHANNEL_ID }}" \ + --arg slack_message_url "${{ steps.slack-success.outputs.slack_url }}" \ + '. + { + slack_ts: $slack_ts, + slack_channel_id: $slack_channel_id, + slack_message_url: $slack_message_url + }' result.json > result_with_slack.json + mv result_with_slack.json result.json + + echo "Updated result.json with Slack notification info:" + cat result.json | jq '.' + + - name: Upload publish result artifact + if: always() && steps.create-release-info.outcome == 'success' + uses: actions/upload-artifact@v4 + with: + name: release_info + path: result.json + retention-days: 90 + + - name: Send Failure Slack notification + if: failure() + uses: ./.github/actions/slack-notification + with: + slack_func: slack_format_failure_message + slack_channel_id: ${{ vars.SLACK_CHANNEL_ID }} + release_tag: ${{ github.event.inputs.release_tag }} + env: ${{ steps.validate-inputs.outputs.env_name }} + message: ":ubuntu: SNAP package upload failed" + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/tags.yml b/.github/workflows/tags.yml deleted file mode 100644 index 99dd5fa..0000000 --- a/.github/workflows/tags.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Tagged Packages - -on: - push: - tags: - - '[0-9]+.[0-9]+*' - -jobs: - build: - strategy: - fail-fast: false - matrix: - include: - - architecture: amd64 - runner: ubuntu-24.04 - - architecture: arm64 - runner: ubuntu24-arm64-4-16 - - runs-on: ${{ matrix.runner }} - - steps: - - uses: actions/checkout@v4 - - name: Determine version - run: | - echo "VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV - - - uses: actions/checkout@v4 - with: - repository: redis/redis - path: redis - ref: ${{ env.VERSION }} - - - name: Setup Snapcraft - run: | - sudo snap install snapcraft --classic - - - uses: canonical/setup-lxd@v0.1.2 - - name: Build Snap - env: - SNAPCRAFT_BUILD_INFO: 1 - run: | - sudo snapcraft - - - name: Upload - run: | - for f in *.snap; do snapcraft upload --release=stable $f; done - env: - SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAP_TOKEN}} diff --git a/.github/workflows/unstable.yml b/.github/workflows/unstable.yml index 13981b0..b17e624 100644 --- a/.github/workflows/unstable.yml +++ b/.github/workflows/unstable.yml @@ -1,216 +1,33 @@ +# This wokrflow is for building and publishing nightly unstable builds of Redis with edge risk level. name: Unstable on: workflow_dispatch: - schedule: - - cron: '0 0 * * *' - pull_request: - paths: - - 'snap/**' - - '.github/workflows/**' + workflow_call: jobs: build: - strategy: - fail-fast: false - matrix: - include: - - architecture: amd64 - runner: ubuntu-24.04 - - architecture: arm64 - runner: ubuntu24-arm64-4-16 + uses: ./.github/workflows/build-n-test.yml + with: + release_tag: unstable - runs-on: ${{ matrix.runner }} - - steps: - - uses: actions/checkout@v4 - - uses: actions/checkout@v4 - with: - repository: redis/redis - path: redis - ref: '8.4.0' - - - name: Setup Snapcraft - run: | - sudo snap install snapcraft --classic - - - uses: canonical/setup-lxd@v0.1.2 - - name: Build Snap - env: - SNAPCRAFT_BUILD_INFO: 1 - run: | - sudo snapcraft - - - name: Upload - if: github.ref == 'refs/heads/master' - run: | - for f in *.snap; do snapcraft upload --release=edge $f; done - env: - SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAP_TOKEN}} - - - name: Upload to artifacts - uses: actions/upload-artifact@v4 - with: - name: redis-snap-${{ matrix.architecture }}-${{ github.sha }} - path: | - *.snap - retention-days: 1 - - test: + publish: needs: build - strategy: - fail-fast: false - matrix: - include: - # AMD64 runners - - architecture: amd64 - os: ubuntu-22.04 - runner: ubuntu-22.04 - - architecture: amd64 - os: ubuntu-24.04 - runner: ubuntu-24.04 - - # ARM64 runners - - architecture: arm64 - os: ubuntu-22.04 - runner: ubuntu22-arm64-2-8 - - architecture: arm64 - os: ubuntu-24.04 - runner: ubuntu24-arm64-2-8 - - runs-on: ${{ matrix.runner }} - + runs-on: ubuntu-24.04 steps: - - name: Setup test environment - run: | - echo "Testing on ${{ matrix.os }} for ${{ matrix.architecture }}" - echo "System information:" - uname -a - lsb_release -a - - - name: Download artifact - uses: actions/download-artifact@v4 + - name: Checkout repository + uses: actions/checkout@v4 with: - name: redis-snap-${{ matrix.architecture }}-${{ github.sha }} - path: ./snap-artifacts - - - name: Verify artifacts - run: | - ls -la ./snap-artifacts - echo "Found snap files:" - find ./snap-artifacts -name "*.snap" - - - name: Install Redis snap package - run: | - SNAP_FILE=$(ls snap-artifacts/*.snap) - echo "Installing snap: $SNAP_FILE" - sudo snap install --dangerous $SNAP_FILE - - - name: Prepare config test - run: | - sudo sed -i 's/dump.rdb/dump-preconfigured.rdb/g' /var/snap/redis/common/etc/redis/redis.conf - - - name: Verify Redis installation and start Redis - run: | - snap list | grep redis - snap services | grep redis || echo "Redis service not found." - # service is started by default on install, but we need to reapply updated config - sudo snap restart redis.server - - - name: Basic Sanity Tests - run: | - for i in {1..5}; do redis.cli ping &>/dev/null && break || echo "Waiting for Redis... $i" && sleep 1; done - redis.cli info server || { echo "Cannot get server info"; exit 1; } - - - name: Configuration Tests - run: | - [ "$(redis.cli CONFIG GET dbfilename | tail -1 )" = "dump-preconfigured.rdb" ] || \ - { echo "Configuration test failed: - expected: 'dump-preconfigured.rdb' - got : '$(redis.cli CONFIG GET dbfilename)'"; exit 1; } - # dbfilename is immutable, so use something else that won't become a default - redis.cli CONFIG SET tls-protocols "TLSv1.2" - redis.cli CONFIG REWRITE - grep 'tls-protocols "TLSv1.2"' /var/snap/redis/common/etc/redis/redis.conf || \ - { echo "Configuration REWRITE test failed: - expected: 'tls-protocols \"TLSv1.2\"' - got : '$(grep tls-protocols /var/snap/redis/common/etc/redis/redis.conf)'"; exit 1; } - - - name: Verify installed modules - run: | - modules=$(redis.cli module list) - echo "Installed modules:" - echo "$modules" - missing_modules=() - for module in "bf" "search" "timeseries" "ReJSON"; do - if ! echo "$modules" | grep -q "$module"; then - missing_modules+=("$module") - fi - done - if [ ${#missing_modules[@]} -eq 0 ]; then - echo "All required modules are installed" - else - echo "The following modules are missing: ${missing_modules[*]}" - exit 1 - fi - - - name: Test RedisBloom - run: | - redis.cli BF.ADD popular_keys "redis:hash" - redis.cli BF.ADD popular_keys "redis:set" - [ "$(redis.cli BF.EXISTS popular_keys "redis:hash")" = "1" ] || \ - { echo "RedisBloom test failed: 'redis:hash' not found"; exit 1; } - [ "$(redis.cli BF.EXISTS popular_keys "redis:list")" = "0" ] || \ - { echo "RedisBloom test failed: 'redis:list' found unexpectedly"; exit 1; } - echo "RedisBloom test passed successfully" - - - name: Test RediSearch - run: | - redis.cli FT.CREATE redis_commands ON HASH PREFIX 1 cmd: SCHEMA name TEXT SORTABLE description TEXT - redis.cli HSET cmd:set name "SET" description "Set the string value of a key" - redis.cli HSET cmd:get name "GET" description "Get the value of a key" - result=$(redis.cli FT.SEARCH redis_commands "value") - if echo "$result" | grep -q "Set the string value of a key" && \ - echo "$result" | grep -q "Get the value of a key"; then - echo "RediSearch test passed successfully" - else - echo "RediSearch test failed: expected commands not found in search results" - exit 1 - fi - - - name: Test RedisTimeSeries - run: | - redis.cli TS.CREATE redis:cpu:usage RETENTION 86400 - redis.cli TS.ADD redis:cpu:usage "*" 80 - redis.cli TS.ADD redis:cpu:usage "*" 65 - redis.cli TS.ADD redis:cpu:usage "*" 70 - result=$(redis.cli TS.RANGE redis:cpu:usage - + COUNT 3) - if echo "$result" | grep -q "80" && \ - echo "$result" | grep -q "65" && \ - echo "$result" | grep -q "70"; then - echo "RedisTimeSeries test passed successfully" - else - echo "RedisTimeSeries test failed: expected values not found in time series" - exit 1 - fi - - - name: Test ReJSON - run: | - redis.cli JSON.SET redis:config $ '{"maxmemory":"2gb","maxmemory-policy":"allkeys-lru"}' - result=$(redis.cli JSON.GET redis:config $.maxmemory-policy) - cleaned_result=$(echo $result | tr -d '[]"') - if [ "$cleaned_result" = "allkeys-lru" ]; then - echo "ReJSON test passed successfully" - else - echo "ReJSON test failed: expected 'allkeys-lru', got $result" - exit 1 - fi - - - name: Check Redis snap status - run: | - snap info redis - - - name: Cleanup - if: always() - run: | - sudo snap remove redis || true + ref: >- + ${{ (github.ref_name == 'unstable' + || github.event_name == 'workflow_call' + || github.event_name == 'schedule') + && 'unstable' + || '' + }} + + - name: Upload all architectures to Snap Store + uses: ./.github/actions/upload + with: + risk_level: 'edge' + snapcraft_store_credentials: ${{ secrets.SNAP_TOKEN }} diff --git a/.redis_versions.json b/.redis_versions.json new file mode 100644 index 0000000..17fb84c --- /dev/null +++ b/.redis_versions.json @@ -0,0 +1,6 @@ +{ + "stable": "8.4.0", + "candidate": "8.4.0", + "edge": "unstable", + "_description": "This file is used mostly to inform automation flows about the latest versions for different risk levels and in PR workflow. Actual SNAP versions are determined in snap/snapcraft.yaml based on release.h. The versions in this file should be in sync but they can technically go out of sync in case of error." +} diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index a86d72c..b9eab03 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -76,7 +76,7 @@ parts: source: conf-dist organize: redis.conf: conf-dist/redis.conf - + cmake-install: plugin: nil override-build: | @@ -84,7 +84,7 @@ parts: snapcraftctl build build-packages: - snapd - + redis: after: [cmake-install] plugin: make @@ -99,7 +99,7 @@ parts: make -j4 PREFIX=${SNAPCRAFT_PART_INSTALL}/usr make install VER=`sed -n 's/^.* REDIS_VERSION "\(.*\)"$/\1/g p' < src/version.h` - if [ "$VER" = "999.999.999" ]; then + if [ "$VER" = "255.255.255" ]; then GITSHA=`sed -n 's/^.* REDIS_GIT_SHA1 "\(.*\)"$/\1/g p' < src/release.h` VER="unstable-$GITSHA" fi