Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c34f41a
add Debug and remove explicit language declaration
aleks-ivanov Jan 13, 2021
e6b7d85
add comment for the pagefile step and clean up the workflow
aleks-ivanov Jan 13, 2021
aeace53
create CI-CD_DOCUMENTATION.md and add Dependabot entry
aleks-ivanov Jan 13, 2021
c2305bf
Merge pull request #1 from AleksIvanovSinglet/feature/dependabot
kulov Jan 15, 2021
bbd56b0
Merge pull request #2 from AleksIvanovSinglet/feature/codeql
kulov Jan 15, 2021
234b9c5
Merge pull request #3 from AleksIvanovSinglet/feature/dependabot-docs
kulov Jan 15, 2021
80acb42
Add SonarCloud. (#4)
szlatkow Jan 15, 2021
566e61c
add CodeQL entry to documentation
aleks-ivanov Jan 18, 2021
98e9093
Merge pull request #5 from AleksIvanovSinglet/feature/codeql-docs
kulov Jan 18, 2021
d5dc611
add Manual workflow run entry to documentation
aleks-ivanov Jan 18, 2021
1eec010
correct step three of Manual run entry
aleks-ivanov Jan 18, 2021
d82ae8c
Merge pull request #6 from AleksIvanovSinglet/feature/manual-run-docs
kulov Jan 18, 2021
35409ab
add initial entry for the release sequence
aleks-ivanov Jan 19, 2021
fe00710
add code scanning alerts bulk dismissal yml and test jq installation
aleks-ivanov Jan 22, 2021
3cf21c3
test jq installation
aleks-ivanov Jan 22, 2021
89970fe
test bulk alert dismissal script
aleks-ivanov Jan 22, 2021
aeca8dd
test secrets as variable vault
aleks-ivanov Jan 22, 2021
8027811
remove push from workflow triggers
aleks-ivanov Jan 22, 2021
a857401
Merge pull request #8 from AleksIvanovSinglet/feature/csa-bulk-dismissal
kulov Jan 22, 2021
763f49b
Merge pull request #7 from AleksIvanovSinglet/feature/release-init-docs
kulov Jan 22, 2021
6d88de0
Delete CI-CD Documentation.md
kulov Jan 22, 2021
4c29e1b
add documentation entry for the 'Code scanning alerts bulk dismissal'
aleks-ivanov Jan 25, 2021
645167b
clear the PAT step
aleks-ivanov Jan 25, 2021
8c89b9d
add some clarifications
aleks-ivanov Jan 25, 2021
1143696
fix a syntactical mistake in CodeQL entry
aleks-ivanov Jan 25, 2021
e33be22
Merge pull request #9 from AleksIvanovSinglet/feature/csa-dismissal-docs
kulov Jan 26, 2021
f039c75
Test sonarcloud without GITHUB_TOKEN.
szlatkow Jan 26, 2021
cd634b2
Update GITHUB_TOKEN
szlatkow Jan 26, 2021
4485bc9
Update actions/cache@v1 to v2.
szlatkow Jan 26, 2021
4ac8553
remove Release entry from docs
aleks-ivanov Jan 26, 2021
8451f6f
Merge pull request #11 from AleksIvanovSinglet/feature/release-doc-re…
kulov Jan 26, 2021
b26569a
Change SONAR_ACCESS_TOKEN to SONAR_GITHUB_TOKEN.
szlatkow Jan 26, 2021
87f51c9
Change the name frin SIBAR_ACCESS_TOKEN to SONAR_GITHUB_TOKEN.
szlatkow Jan 26, 2021
f813926
Merge pull request #12 from szlatkow/feature/sonarcloud-test-authenti…
kulov Jan 26, 2021
55a555a
Merge pull request #13 from szlatkow/feature/sonarcloud-cache-update-v2
kulov Jan 26, 2021
98450c4
Skip running SonarCloud on PR. (#14)
szlatkow Jan 26, 2021
c0b599d
fix a syntax mistake in the CSABR entry
aleks-ivanov Jan 26, 2021
e923c32
Merge pull request #15 from AleksIvanovSinglet/feature/fix-syntax-mis…
kulov Jan 26, 2021
e9cc89c
improve CSABD pipeline
aleks-ivanov Jan 29, 2021
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
27 changes: 17 additions & 10 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ jobs:
analyze:
name: codeql-analysis
runs-on: windows-latest
strategy:
matrix:
configuration: [Debug, Release]
env:
Solution_Name: src\Notepads.sln
Project_Path: src\Notepads\Notepads.csproj
Expand All @@ -19,37 +22,41 @@ jobs:
id: checkout_repo
uses: actions/checkout@v2

- name: configure Pagefile
# Due to the insufficient memory allocated by default, CodeQL sometimes requires more to be manually allocated
- name: Configure Pagefile
id: config_pagefile
uses: al-cheb/[email protected]
with:
minimum-size: 8GB
maximum-size: 32GB
disk-root: "D:"

# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
- name: Setup MSBuild
id: setup_msbuild
uses: microsoft/setup-msbuild@v1

- name: Restore the application
run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration
- name: Restore application
id: restore_app
env:
Configuration: Release
Configuration: ${{ matrix.configuration }}
run: |
msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration

- name: Initialize CodeQL
id: init_codeql
uses: github/codeql-action/init@v1
with:
languages: csharp
queries: security-and-quality

- name: Build
run: |
msbuild $env:Project_Path /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode /p:AppxBundle=$env:Appx_Bundle /p:AppxPackageSigningEnabled=false /p:AppxBundlePlatforms="$env:Appx_Bundle_Platforms"
- name: Build application
id: build_app
env:
Appx_Bundle: Always
Appx_Bundle_Platforms: x86|x64
Appx_Package_Build_Mode: StoreUpload
Configuration: Release
Configuration: ${{ matrix.configuration }}
run: |
msbuild $env:Project_Path /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode /p:AppxBundle=$env:Appx_Bundle /p:AppxPackageSigningEnabled=false /p:AppxBundlePlatforms="$env:Appx_Bundle_Platforms"

- name: Perform CodeQL Analysis
id: analyze_codeql
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/csa-bulk-dismissal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Code scanning alerts bulk dismissal

on: [workflow_dispatch]

jobs:
dismiss-alerts:
name: Dismiss alerts
runs-on: ubuntu-latest
env:
# Settings
OWNER: ${{ secrets.REPO_OWNER_VAR }} # verbatim from URL
PROJECT_NAME: ${{ secrets.REPO_NAME_VAR }} # verbatim from URL
ACCESS_TOKEN: ${{ secrets.CSA_ACCESS_TOKEN }} # requires security_events read/write permissions
DISMISS_REASON: ${{ secrets.DISMISS_REASON_VAR }} # "false positive", "won't fix" or "used in tests".
ALERTS_PER_PAGE: 100
ALERT_DESCRIPTION: ${{ secrets.ALERT_DESCRIPTION }}
steps:
- name: Install jq
id: install_jq
uses: r26d/jq-action@master
with:
cmd: jq -n env

- name: Run automation
id: run_automation
shell: bash
run: |
i=1
LIST_OF_ALERTS=$(curl -u $OWNER:$ACCESS_TOKEN -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/$OWNER/$PROJECT_NAME/code-scanning/alerts?state=open&page=$i&per_page=$ALERTS_PER_PAGE"| jq .[].number )

while [ -n "$LIST_OF_ALERTS" ]
do
echo -n $LIST_OF_ALERTS" " >> "data.json"

((i=i+1))

LIST_OF_ALERTS=$(curl -u $OWNER:$ACCESS_TOKEN -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/$OWNER/$PROJECT_NAME/code-scanning/alerts?state=open&page=$i&per_page=$ALERTS_PER_PAGE"| jq .[].number )
done

LIST_OF_INDEXES=$(cat data.json)

for index in $LIST_OF_INDEXES
do
ALERT_DESC=$(curl -u $OWNER:$ACCESS_TOKEN -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/$OWNER/$PROJECT_NAME/code-scanning/alerts/$index" | jq .rule.description)
REQUIRED_STR=$ALERT_DESCRIPTION

if [ "$ALERT_DESC" == "$REQUIRED_STR" ]; then
ALERT_URL="https://api.github.com/repos/$OWNER/$PROJECT_NAME/code-scanning/alerts/$index"

curl -u $OWNER:$ACCESS_TOKEN -X PATCH -H "Accept: application/vnd.github.v3+json" $ALERT_URL -d '{"state":"dismissed","dismissed_reason":"'"$DISMISS_REASON"'"}'
fi
done

rm -f data.json

# Built with ❤ by [Pipeline Foundation](http://pipeline.foundation)
99 changes: 99 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Build

on: [push, pull_request, workflow_dispatch]

jobs:

build:

strategy:
matrix:
configuration: [Debug, Release]
env:
Solution_Name: src\Notepads.sln
Project_Path: src\Notepads\Notepads.csproj

runs-on: windows-latest
steps:

- name: Set up JDK 11
id: Setup_JDK
uses: actions/setup-java@v1
with:
java-version: 1.11

- uses: actions/checkout@v2
id: actions_checkout
with:
fetch-depth: 50

- if: github.event_name != 'pull_request'
name: Cache SonarCloud packages
id: cache_sonar_packages
uses: actions/cache@v2
with:
path: ~\sonar\cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar

- if: github.event_name != 'pull_request'
name: Cache SonarCloud scanner
id: cache_sonar_scanner
uses: actions/cache@v2
with:
path: .\.sonar\scanner
key: ${{ runner.os }}-sonar-scanner
restore-keys: ${{ runner.os }}-sonar-scanner

- if: github.event_name != 'pull_request' && steps.cache_sonar_scanner.outputs.cache-hit != 'true'
name: Install SonarCloud scanner
id: install_sonar_scanner
shell: powershell
run: |
New-Item -Path .\.sonar\scanner -ItemType Directory
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner

- if: github.event_name != 'pull_request'
name: Lowercase string generator
id: lowercase_string_gen
shell: powershell
run: |
$LOWERCASE_OWNER = "${{ github.repository_owner }}".ToLower()
echo "::set-output name=owner_name::$LOWERCASE_OWNER"

- if: github.event_name != 'pull_request'
name: Initialize SonarCloud scanner
id: init_sonar_scanner
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: .\.sonar\scanner\dotnet-sonarscanner begin /k:"${{ github.repository_owner }}_${{ github.event.repository.name }}" /o:"${{ steps.lowercase_string_gen.outputs.owner_name }}" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io"

# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
- name: Setup MSBuild
id: setup_msbuild
uses: microsoft/setup-msbuild@v1

- name: Restore the application
id: restore_application
run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration
env:
Configuration: ${{ matrix.configuration }}

- name: Build
id: build_app
run: msbuild $env:Project_Path /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode /p:AppxBundle=$env:Appx_Bundle /p:AppxPackageSigningEnabled=false /p:AppxBundlePlatforms="$env:Appx_Bundle_Platforms"
env:
Appx_Bundle: Always
Appx_Bundle_Platforms: x86|x64
Appx_Package_Build_Mode: StoreUpload
Configuration: ${{ matrix.configuration }}

- if: github.event_name != 'pull_request'
name: Send SonarCloud results
id: send_sonar_results
env:
GITHUB_TOKEN: ${{ secrets.SONAR_GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
158 changes: 158 additions & 0 deletions CI-CD_DOCUMENTATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Notepads CI/CD documentation

* after merging the PR, the first run of the main workflow will not complete successfully, because it requires specific setup explained in this documentation

## *. Run workflow manually

Once you've set up all the steps above correctly, you should be able to successfully complete a manual execution of the main workflow "Notepads CI/CD Pipeline".

1. Go to GitHub project -> "Actions" tab

2. From the "Workflows" list on the left, click on "Notepads CI/CD Pipeline"

3. On the right, next to the "This workflow has a workflow_dispatch event trigger" label, click on the "Run workflow" dropdown, make sure the default branch is selected (if not manually changed, should be main or master) in the "Use workflow from" dropdown and click the "Run workflow" button

![Actions_workflow_dispatch](/ScreenShots/CI-CD_DOCUMENTATION/Actions_workflow_dispatch.png)

4. Once the workflow run has completed successfully, move on to the next step of the documentation

NOTE: **screenshots are only exemplary**

<br>

## *. Set up Dependabot

Dependabot is a GitHub native security tool that goes through the dependencies in your project and creates alerts, and PRs with updates when a new and/or non-vulnerable version is found.

- for PRs with version updates, this pipeline comes pre-configured for all current dependency sources in your project, so at "Insights" tab -> "Dependency graph" -> "Dependabot", you should be able to see all tracked sources of dependencies, when they have been checked last and view a full log of the last check

![Dependabot_tab](/ScreenShots/CI-CD_DOCUMENTATION/Dependabot_tab.png)

![Dependabot_log_page](/ScreenShots/CI-CD_DOCUMENTATION/Dependabot_log_page.png)

### Set up security alerts and updates
##### - GitHub, through Dependabot, also natively offers a security check for vulnerable dependencies

1. Go to "Settings" tab of your repo

2. Go to "Security&Analysis" section

3. Click "Enable" for both "Dependabot alerts" and "Dependabot security updates"

- By enabling "Dependabot alerts", you would be notified for any vulnerable dependencies in your project. At "Security" tab -> "Dependabot alerts", you can manage all alerts. By clicking on an alert, you would be able to see a detailed explanation of the vulnerability and a viable solution.

![Dependabot_alerts_page](/ScreenShots/CI-CD_DOCUMENTATION/Dependabot_alerts_page.png)

![Dependabot_alert_page](/ScreenShots/CI-CD_DOCUMENTATION/Dependabot_alert_page.png)

- By enabling "Dependabot security updates", you authorize Dependabot to create PRs specifically for **security updates**

![Dependabot_PRs](/ScreenShots/CI-CD_DOCUMENTATION/Dependabot_PRs.png)

### Set up Dependency graph
##### - The "Dependency graph" option should be enabled by default for all public repos, but in case it isn't:

1. Go to "Settings" tab of your repo

2. Go to "Security&Analysis" section

3. Click "Enable" for the "Dependency graph" option

- this option enables the "Insights" tab -> "Dependency graph" section -> "Dependencies" tab, in which all the dependencies for the project are listed, under the different manifests they are included in

![Dependabot_dependency_graph](/ScreenShots/CI-CD_DOCUMENTATION/Dependabot_dependency_graph.png)

NOTE: **screenshots are only exemplary**

<br>

## *. CodeQL

CodeQL is GitHub's own industry-leading semantic code analysis engine. CodeQL requires no setup, because it comes fully pre-configured by us.

To activate it and see its results, only a push commit or a merge of a PR to the default branch of your repository, is required.

We've also configured CodeQL to run on schedule, so every day at 8:00AM UTC, it automatically tests the code.

- you can see the results here at **Security** tab -> **Code scanning alerts** -> **CodeQL**:

![CodeQL_results](/ScreenShots/CI-CD_DOCUMENTATION/CodeQL_results.png)

- on the page of each result, you can see an explanation of what the problem is and also one or more solutions:

![CodeQL_alert_page](/ScreenShots/CI-CD_DOCUMENTATION/CodeQL_alert_page.png)

### Code scanning alerts bulk dismissal
##### - currently, GitHub allows for only 25 code scanning alerts to be dismissed at a time. Sometimes, you might have hundreds you would like to dismiss, so you will have to click many times and wait for a long time to dismiss them. Via the "csa-bulk-dismissal.yml", you would be able to that with one click.

#### 1. Setup

1. In your repo, go to the Settings tab -> Secrets

![CSA_secrets](/ScreenShots/CI-CD_DOCUMENTATION/CSA_secrets.png)

2. Add the following secrets with the name and the corresponding value, by at the upper right of the section, clicking on the **New repository secret** button :

![CSA_new_secret](/ScreenShots/CI-CD_DOCUMENTATION/CSA_new_secret.png)

![CSA_secret_add](/ScreenShots/CI-CD_DOCUMENTATION/CSA_secret_add.png)

- REPO_OWNER_VAR (secret name) - add repo owner's name, verbatim from GitHub URL (secret value)

![CSA_url_owner](/ScreenShots/CI-CD_DOCUMENTATION/CSA_url_owner.png)

- REPO_NAME_VAR - add repo's name, verbatim from GitHub URL

![CSA_url_repo](/ScreenShots/CI-CD_DOCUMENTATION/CSA_url_repo.png)

- CSA_ACCESS_TOKEN - add a PAT with "security_events" permission.

1. In a new tab open GitHub, at the top right corner, click on your profile picture and click on **Settings** from the dropdown.

![CSA_new_pat_1](/ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_1.png)

2. Go to Developer Settings -> Personal access tokens.

![CSA_new_pat_2](/ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_2.png)

![CSA_new_pat_3](/ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_3.png)

3. Click the **Generate new token** button and enter password if prompted.

![CSA_new_pat_4](/ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_4.png)

4. Name the token "CSA_ACCESS_TOKEN". From the permissions list, choose only "security_events", and at the bottom click on the **Generate token** button.

![CSA_new_pat_5](/ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_5.png)

5. Copy the token value and paste it in the secret "CSA_ACCESS_TOKEN", you created in the previous tab.

![CSA_new_pat_6](/ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_6.png)

- DISMISS_REASON_VAR - this secret refers to the reason why you dismissed the code scanning alert. Use the appropriate one, out of the three available options: "false positive", "won't fix" or "used in tests". (copy the option value **without** the quotes)

#### 2. Execution

1. In your repo, click on the Actions tab and on the left, in the Workflows list, click on the "Code scanning alerts bulk dismissal"

![CSA_execute_1](/ScreenShots/CI-CD_DOCUMENTATION/CSA_execute_1.png)

2. On the right, click on the "Run workflow" dropdown. Under "Use workflow from" choose your default branch (usually main/master) and click on the **Run workflow** button

![CSA_execute_2](/ScreenShots/CI-CD_DOCUMENTATION/CSA_execute_2.png)

3. If everything was set up currently in the "Setup" phase, the "Code scanning alerts bulk dismissal" workflow is going to be executed successfully, which after some time, would result in **all** previously open code scanning alerts be dismissed

![CSA_execute_3](/ScreenShots/CI-CD_DOCUMENTATION/CSA_execute_3.png)

![CSA_execute_4](/ScreenShots/CI-CD_DOCUMENTATION/CSA_execute_4.png)

![CSA_execute_5](/ScreenShots/CI-CD_DOCUMENTATION/CSA_execute_5.png)

NOTE: "closed" refers to "dismissed" alerts

NOTE: **screenshots are only exemplary**

#

Built with ❤ by [Pipeline Foundation](http://pipeline.foundation)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_execute_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_execute_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_execute_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_execute_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_new_pat_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_secrets.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/CI-CD_DOCUMENTATION/CSA_url_owner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.