Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/upload-artifact/releases">actions/upload-artifact's releases</a>.</em></p> <blockquote> <h2>v4.0.0</h2> <h2>What's Changed</h2> <p>The release of upload-artifact@v4 and download-artifact@v4 are major changes to the backend architecture of Artifacts. They have numerous performance and behavioral improvements.</p> <p>For more information, see the <a href="https://github.com/actions/toolkit/tree/main/packages/artifact"><code>@actions/artifact</code></a> documentation.</p> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/vmjoseph"><code>@vmjoseph</code></a> made their first contribution in <a href="https://redirect.github.com/actions/upload-artifact/pull/464">actions/upload-artifact#464</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/upload-artifact/compare/v3...v4.0.0">https://github.com/actions/upload-artifact/compare/v3...v4.0.0</a></p> <h2>v3.1.3</h2> <h2>What's Changed</h2> <ul> <li>chore(github): remove trailing whitespaces by <a href="https://github.com/ljmf00"><code>@ljmf00</code></a> in <a href="https://redirect.github.com/actions/upload-artifact/pull/313">actions/upload-artifact#313</a></li> <li>Bump <code>@actions/artifact</code> version to v1.1.2 by <a href="https://github.com/bethanyj28"><code>@bethanyj28</code></a> in <a href="https://redirect.github.com/actions/upload-artifact/pull/436">actions/upload-artifact#436</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/upload-artifact/compare/v3...v3.1.3">https://github.com/actions/upload-artifact/compare/v3...v3.1.3</a></p> <h2>v3.1.2</h2> <ul> <li>Update all <code>@actions/*</code> NPM packages to their latest versions- <a href="https://redirect.github.com/actions/upload-artifact/issues/374">#374</a></li> <li>Update all dev dependencies to their most recent versions - <a href="https://redirect.github.com/actions/upload-artifact/issues/375">#375</a></li> </ul> <h2>v3.1.1</h2> <ul> <li>Update actions/core package to latest version to remove <code>set-output</code> deprecation warning <a href="https://redirect.github.com/actions/upload-artifact/issues/351">#351</a></li> </ul> <h2>v3.1.0</h2> <h2>What's Changed</h2> <ul> <li>Bump <code>@actions/artifact</code> to v1.1.0 (<a href="https://redirect.github.com/actions/upload-artifact/pull/327">actions/upload-artifact#327</a>) <ul> <li>Adds checksum headers on artifact upload (<a href="https://redirect.github.com/actions/toolkit/pull/1095">actions/toolkit#1095</a>) (<a href="https://redirect.github.com/actions/toolkit/pull/1063">actions/toolkit#1063</a>)</li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="c7d193f32e"><code>c7d193f</code></a> Merge pull request <a href="https://redirect.github.com/actions/upload-artifact/issues/466">#466</a> from actions/v4-beta</li> <li><a href="13131bb095"><code>13131bb</code></a> licensed cache</li> <li><a href="4a6c273b98"><code>4a6c273</code></a> Merge branch 'main' into v4-beta</li> <li><a href="f391bb91a3"><code>f391bb9</code></a> Merge pull request <a href="https://redirect.github.com/actions/upload-artifact/issues/465">#465</a> from actions/robherley/v4-documentation</li> <li><a href="9653d03c4b"><code>9653d03</code></a> Apply suggestions from code review</li> <li><a href="875b630764"><code>875b630</code></a> add limitations section</li> <li><a href="ecb21463e9"><code>ecb2146</code></a> add compression example</li> <li><a href="5e7604f84a"><code>5e7604f</code></a> trim some repeated info</li> <li><a href="d6437d0758"><code>d6437d0</code></a> naming</li> <li><a href="1b56155703"><code>1b56155</code></a> s/v4-beta/v4/g</li> <li>Additional commits viewable in <a href="https://github.com/actions/upload-artifact/compare/v3...v4">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details>
398 lines
14 KiB
YAML
398 lines
14 KiB
YAML
name: Longevity Testing
|
|
on:
|
|
schedule:
|
|
# Run every day at 04:00 GMT (roughly 8pm PST)
|
|
- cron: "0 4 * * *"
|
|
workflow_dispatch:
|
|
inputs:
|
|
user:
|
|
description: 'User to run longevity test on'
|
|
|
|
permissions:
|
|
# required to retrieve AWS credentials
|
|
id-token: write
|
|
contents: write
|
|
|
|
# cancel currently running jobs if a new version of the branch is pushed
|
|
concurrency:
|
|
group: longevity_testing-${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
SetM365App:
|
|
uses: alcionai/corso/.github/workflows/accSelector.yaml@main
|
|
|
|
Longevity-Tests:
|
|
needs: [ SetM365App ]
|
|
environment: Testing
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
# Need these in the local env so that corso can read them
|
|
AZURE_CLIENT_ID: ${{ secrets[needs.SetM365App.outputs.client_id_env] }}
|
|
AZURE_CLIENT_SECRET: ${{ secrets[needs.SetM365App.outputs.client_secret_env] }}
|
|
AZURE_TENANT_ID: ${{ secrets.TENANT_ID }}
|
|
CORSO_PASSPHRASE: ${{ secrets.INTEGRATION_TEST_CORSO_PASSPHRASE }}
|
|
# re-used values
|
|
CORSO_LOG_DIR: ${{ github.workspace }}/src/testlog
|
|
CORSO_LOG_FILE: ${{ github.workspace }}/src/testlog/run-longevity.log
|
|
RESTORE_DEST_PFX: Corso_Test_Longevity_
|
|
TEST_USER: ${{ github.event.inputs.user != '' && github.event.inputs.user || vars.CORSO_M365_TEST_USER_ID }}
|
|
PREFIX: 'longevity'
|
|
|
|
# Options for retention.
|
|
RETENTION_MODE: GOVERNANCE
|
|
# Time to retain blobs for in hours.
|
|
RETENTION_DURATION: 216
|
|
defaults:
|
|
run:
|
|
working-directory: src
|
|
|
|
############################################################################
|
|
# setup
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0 # needed to get latest tag
|
|
|
|
- name: Setup Golang with cache
|
|
uses: magnetikonline/action-golang-cache@v4
|
|
with:
|
|
go-version-file: src/go.mod
|
|
|
|
- run: |
|
|
go build -o longevity-test ./cmd/longevity_test
|
|
go build -o s3checker ./cmd/s3checker
|
|
|
|
- name: Get version string
|
|
id: version
|
|
run: |
|
|
echo version=$(git describe --tags --abbrev=0) | tee -a $GITHUB_OUTPUT
|
|
|
|
# Checkout the .github directory at the original branch's ref so we have a
|
|
# stable view of the actions.
|
|
- name: Code Checkout
|
|
working-directory: ${{ github.workspace }}
|
|
run: |
|
|
git checkout ${{ steps.version.outputs.version }}
|
|
git checkout ${{ github.ref }} -- .github
|
|
|
|
- run: go build -o corso
|
|
timeout-minutes: 10
|
|
|
|
- run: mkdir ${CORSO_LOG_DIR}
|
|
|
|
# Use shorter-lived credentials obtained from assume-role since these
|
|
# runs haven't been taking long.
|
|
- name: Configure AWS credentials from Test account
|
|
uses: aws-actions/configure-aws-credentials@v4
|
|
timeout-minutes: 10
|
|
with:
|
|
role-to-assume: ${{ secrets.AWS_IAM_ROLE }}
|
|
role-session-name: integration-testing
|
|
aws-region: us-east-1
|
|
|
|
##########################################################################
|
|
# Repository commands
|
|
|
|
- name: Version Test
|
|
timeout-minutes: 10
|
|
run: |
|
|
./corso --version | grep -c 'Corso version:'
|
|
|
|
- name: Repo init test
|
|
id: repo-init
|
|
timeout-minutes: 10
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\nRepo init test\n" >> ${{ env.CORSO_LOG_FILE }}
|
|
./corso repo init s3 \
|
|
--no-stats \
|
|
--hide-progress \
|
|
--retention-mode $(echo "${{ env.RETENTION_MODE }}" | tr '[:upper:]' '[:lower:]') \
|
|
--retention-duration "${{ env.RETENTION_DURATION }}h" \
|
|
--extend-retention \
|
|
--prefix ${{ env.PREFIX }} \
|
|
--bucket ${{ secrets.CI_RETENTION_TESTS_S3_BUCKET }} \
|
|
--succeed-if-exists \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/gotest-repo-init.log
|
|
|
|
if grep -q 'Failed to' ${{ env.CORSO_LOG_DIR }}/gotest-repo-init.log
|
|
then
|
|
echo "Repo could not be initialized"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Repo connect test
|
|
timeout-minutes: 10
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\nRepo connect test\n" >> ${{ env.CORSO_LOG_FILE }}
|
|
./corso repo connect s3 \
|
|
--no-stats \
|
|
--hide-progress \
|
|
--prefix ${{ env.PREFIX }} \
|
|
--bucket ${{ secrets.CI_RETENTION_TESTS_S3_BUCKET }} \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/gotest-repo-connect.log
|
|
|
|
if ! grep -q 'Connected to S3 bucket' ${{ env.CORSO_LOG_DIR }}/gotest-repo-connect.log
|
|
then
|
|
echo "Repo could not be connected"
|
|
exit 1
|
|
fi
|
|
|
|
##########################################################################
|
|
# Exchange
|
|
|
|
- name: Backup exchange test
|
|
id: exchange-test
|
|
timeout-minutes: 30
|
|
run: |
|
|
echo -e "\nBackup Exchange test\n" >> ${CORSO_LOG_FILE}
|
|
./corso backup create exchange \
|
|
--no-stats \
|
|
--mailbox "${TEST_USER}" \
|
|
--hide-progress \
|
|
--json \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/backup_exchange.txt
|
|
|
|
resultjson=$(sed -e '1,/Completed Backups/d' ${{ env.CORSO_LOG_DIR }}/backup_exchange.txt )
|
|
|
|
if [[ $( echo $resultjson | jq -r '.[0] | .stats.errorCount') -ne 0 ]]; then
|
|
echo "backup was not successful"
|
|
exit 1
|
|
fi
|
|
|
|
data=$( echo $resultjson | jq -r '.[0] | .id' )
|
|
echo result=$data >> $GITHUB_OUTPUT
|
|
|
|
##########################################################################
|
|
# Onedrive
|
|
|
|
- name: Backup onedrive test
|
|
id: onedrive-test
|
|
timeout-minutes: 30
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\nBackup OneDrive test\n" >> ${CORSO_LOG_FILE}
|
|
./corso backup create onedrive \
|
|
--no-stats \
|
|
--hide-progress \
|
|
--user "${TEST_USER}" \
|
|
--json \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/backup_onedrive.txt
|
|
|
|
resultjson=$(sed -e '1,/Completed Backups/d' ${{ env.CORSO_LOG_DIR }}/backup_onedrive.txt )
|
|
|
|
if [[ $( echo $resultjson | jq -r '.[0] | .stats.errorCount') -ne 0 ]]; then
|
|
echo "backup was not successful"
|
|
exit 1
|
|
fi
|
|
|
|
data=$( echo $resultjson | jq -r '.[0] | .id' )
|
|
echo result=$data >> $GITHUB_OUTPUT
|
|
|
|
##########################################################################
|
|
# Sharepoint test
|
|
- name: Backup sharepoint test
|
|
id: sharepoint-test
|
|
timeout-minutes: 30
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\nBackup SharePoint test\n" >> ${CORSO_LOG_FILE}
|
|
|
|
./corso backup create sharepoint \
|
|
--no-stats \
|
|
--hide-progress \
|
|
--site "${{ vars.CORSO_M365_TEST_SITE_URL }}" \
|
|
--json \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/backup_sharepoint.txt
|
|
|
|
resultjson=$(sed -e '1,/Completed Backups/d' ${{ env.CORSO_LOG_DIR }}/backup_sharepoint.txt )
|
|
|
|
if [[ $( echo $resultjson | jq -r '.[0] | .stats.errorCount') -ne 0 ]]; then
|
|
echo "backup was not successful"
|
|
exit 1
|
|
fi
|
|
|
|
data=$( echo $resultjson | jq -r '.[0] | .id' )
|
|
echo result=$data >> $GITHUB_OUTPUT
|
|
|
|
##########################################################################
|
|
# Backup Exchange Deletion test
|
|
- name: Backup Delete exchange test
|
|
id: delete-exchange-test
|
|
timeout-minutes: 30
|
|
env:
|
|
SERVICE: "exchange"
|
|
DELETION_DAYS: 10
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\nDelete Backup exchange \n" >> ${CORSO_LOG_FILE}
|
|
./longevity-test
|
|
|
|
##########################################################################
|
|
# Backup Onedrive Deletion test
|
|
- name: Backup Delete onedrive test
|
|
id: delete-onedrive-test
|
|
timeout-minutes: 30
|
|
env:
|
|
SERVICE: "onedrive"
|
|
DELETION_DAYS: 10
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\nDelete Backup onedrive \n" >> ${CORSO_LOG_FILE}
|
|
./longevity-test
|
|
|
|
##########################################################################
|
|
# Backup Sharepoint Deletion test
|
|
- name: Backup Delete Sharepoint test
|
|
id: delete-sharepoint-test
|
|
timeout-minutes: 30
|
|
env:
|
|
SERVICE: "sharepoint"
|
|
DELETION_DAYS: 5
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\nDelete Backup sharepoint \n" >> ${CORSO_LOG_FILE}
|
|
./longevity-test
|
|
|
|
##########################################################################
|
|
# Export OneDrive Test
|
|
- name: OneDrive Export test
|
|
timeout-minutes: 30
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\Export OneDrive test\n" >> ${CORSO_LOG_FILE}
|
|
|
|
echo -e "\Export OneDrive test - first entry\n" >> ${CORSO_LOG_FILE}
|
|
./corso backup list onedrive 2>/dev/null | tail -n+2 | head -n1 | awk '{print $1}' |
|
|
while read -r line; do
|
|
./corso export onedrive \
|
|
"/tmp/corso-export--$line" \
|
|
--no-stats \
|
|
--backup "$line" \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/export_onedrive_first.txt
|
|
done
|
|
|
|
echo -e "\Export OneDrive test - last entry\n" >> ${CORSO_LOG_FILE}
|
|
./corso backup list onedrive 2>/dev/null | tail -n1 | awk '{print $1}' |
|
|
while read -r line; do
|
|
./corso export onedrive \
|
|
"/tmp/corso-export--$line" \
|
|
--no-stats \
|
|
--backup "$line" \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/export_onedrive_last.txt
|
|
done
|
|
|
|
##########################################################################
|
|
# Export SharePoint Test
|
|
- name: SharePoint Export test
|
|
timeout-minutes: 30
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\Export SharePoint test\n" >> ${CORSO_LOG_FILE}
|
|
|
|
echo -e "\Export SharePoint test - first entry\n" >> ${CORSO_LOG_FILE}
|
|
./corso backup list sharepoint 2>/dev/null | tail -n+2 | head -n1 | awk '{print $1}' |
|
|
while read -r line; do
|
|
./corso export sharepoint \
|
|
"/tmp/corso-export--$line" \
|
|
--no-stats \
|
|
--backup "$line" \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/export_sharepoint_first.txt
|
|
done
|
|
|
|
echo -e "\Export SharePoint test - last entry\n" >> ${CORSO_LOG_FILE}
|
|
./corso backup list sharepoint 2>/dev/null | tail -n1 | awk '{print $1}' |
|
|
while read -r line; do
|
|
./corso export sharepoint \
|
|
"/tmp/corso-export--$line" \
|
|
--no-stats \
|
|
--backup "$line" \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/export_sharepoint_last.txt
|
|
done
|
|
|
|
##########################################################################
|
|
# Maintenance test
|
|
- name: Maintenance test Daily
|
|
id: maintenance-test-daily
|
|
timeout-minutes: 30
|
|
run: |
|
|
set -euo pipefail
|
|
echo -e "\n Maintenance test Daily\n" >> ${CORSO_LOG_FILE}
|
|
|
|
# Run with the force flag so it doesn't fail if the github runner
|
|
# hostname isn't what's expected. This is only safe because we can
|
|
# guarantee only one runner will be executing maintenance at a time.
|
|
./corso repo maintenance --mode metadata \
|
|
--no-stats \
|
|
--hide-progress \
|
|
--force \
|
|
--json \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/maintenance_metadata.txt
|
|
|
|
- name: Maintenance test Weekly
|
|
id: maintenance-test-weekly
|
|
timeout-minutes: 30
|
|
run: |
|
|
if [[ $(date +%A) == "Saturday" ]]; then
|
|
set -euo pipefail
|
|
echo -e "\n Maintenance test Weekly\n" >> ${CORSO_LOG_FILE}
|
|
|
|
./corso repo maintenance --mode complete \
|
|
--no-stats \
|
|
--hide-progress \
|
|
--force \
|
|
--json \
|
|
2>&1 | tee ${{ env.CORSO_LOG_DIR }}/maintenance_complete.txt
|
|
|
|
# TODO(ashmrtn): We can also check that non-current versions of
|
|
# blobs don't have their retention extended if we want.
|
|
#
|
|
# Assuming no failures during full maintenance, current versions of
|
|
# objects with the below versions should have retention times that
|
|
# are roughly (now + RETENTION_DURATION). We can explicitly check
|
|
# for this, but leave a little breathing room since maintenance may
|
|
# take some time to run.
|
|
#
|
|
# If we pick a live-retention-duration that is too small then we'll
|
|
# start seeing failures. The check for live objects is a lower bound
|
|
# check.
|
|
#
|
|
# Blob prefixes are as follows:
|
|
# - kopia.blobcfg - repo-wide config
|
|
# - kopia.repository - repo-wide config
|
|
# - p - data pack blobs (i.e. file data)
|
|
# - q - metadata pack blobs (i.e. manifests, directory listings, etc)
|
|
# - x - index blobs
|
|
./s3checker \
|
|
--bucket ${{ secrets.CI_RETENTION_TESTS_S3_BUCKET }} \
|
|
--prefix ${{ env.PREFIX }} \
|
|
--retention-mode ${{ env.RETENTION_MODE }} \
|
|
--live-retention-duration "$((${{ env.RETENTION_DURATION }}-1))h" \
|
|
--object-prefix "kopia.blobcfg" \
|
|
--object-prefix "kopia.repository" \
|
|
--object-prefix "p" \
|
|
--object-prefix "q" \
|
|
--object-prefix "x"
|
|
fi
|
|
|
|
##########################################################################
|
|
# Logging & Notifications
|
|
# Upload the original go test output as an artifact for later review.
|
|
- name: Upload test log
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: longevity-test-log
|
|
path: src/testlog/*
|
|
if-no-files-found: error
|
|
retention-days: 14
|
|
|
|
- name: Notify failure in teams
|
|
if: failure()
|
|
uses: ./.github/actions/teams-message
|
|
with:
|
|
msg: "[FAILED] Longevity Test"
|
|
teams_url: ${{ secrets.TEAMS_CORSO_CI_WEBHOOK_URL }}
|