Skip to content

Bump github.com/99designs/gqlgen from 0.17.49 to 0.17.60 in /api #884

Bump github.com/99designs/gqlgen from 0.17.49 to 0.17.60 in /api

Bump github.com/99designs/gqlgen from 0.17.49 to 0.17.60 in /api #884

name: "Code Analysis"
on:
push:
branches: [master]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 1 * * 4'
jobs:
create-matrix:
runs-on: ubuntu-latest
steps:
- name: Get languages from repo
id: set-matrix
uses: advanced-security/set-codeql-language-matrix@v1
with:
access-token: ${{ secrets.GITHUB_TOKEN }}
endpoint: ${{ github.event.repository.languages_url }}
outputs:
matrix: ${{ steps.set-matrix.outputs.languages }}
analyze:
name: Analyze
needs: create-matrix
if: ${{ needs.create-matrix.outputs.matrix != '[]' }} && github.repository == 'kkovaletp/photoview'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: ${{ fromJSON(needs.create-matrix.outputs.matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# Run further tests
queries: security-extended, security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
anchore:
name: Anchore scan code dependencies
if: github.repository == 'kkovaletp/photoview'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Generate report
id: scan
uses: anchore/scan-action@v5
with:
path: "."
fail-build: false
add-cpes-if-none: true
- name: Upload report
uses: github/codeql-action/upload-sarif@v3
if: ${{ steps.scan.conclusion == 'success' || steps.scan.conclusion == 'failure' }}
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
- name: Scan PR source code
id: scan-fixed
uses: anchore/scan-action@v5
if: always() && github.event_name == 'pull_request'
with:
path: "."
fail-build: false
add-cpes-if-none: true
output-format: json
severity-cutoff: high
only-fixed: true
- name: Prepare JSON
if: ${{ ( steps.scan-fixed.conclusion == 'success' || steps.scan-fixed.conclusion == 'failure' ) && github.event_name == 'pull_request' }}
run: |
jq '{
"|": .matches | map({
"language": .artifact.language,
"id": .vulnerability.id,
"severity": .vulnerability.severity,
"name": .artifact.name,
"version": .artifact.version,
"fix-versions": .vulnerability.fix.versions[0],
"path": .artifact.locations[0].path,
"description": .vulnerability.description
})
}' ${{ steps.scan-fixed.outputs.json }} > vulns.json
cat vulns.json | jq
- name: JSON to Table
uses: Teebra/[email protected]
if: github.event_name == 'pull_request'
with:
json-file: vulns.json
- name: Update Pull Request
uses: actions/github-script@v7
if: github.event_name == 'pull_request'
with:
github-token: ${{ secrets.COMMENT_TOKEN }}
script: |
const fs = require('fs');
let scanResults = fs.readFileSync('output.html', 'utf8');
let output = '';
const comments = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo
});
const botComment = comments.data.find(comment => comment.user.login === 'github-actions[bot]' && comment.body.includes('Anchore'));
output += '#### Anchore Grype scan results:\n';
output += 'Anchore Grype detected vulnerabilities in project dependencies, for which fixed versions are available.\n';
output += 'Please find more details in the "Checks" tab of this PR > "Code scanning results" > "Grype".\n';
if (scanResults) {
output += '\n' + scanResults + '\n';
if (botComment) {
await github.rest.issues.updateComment({
comment_id: botComment.id,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
});
} else {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
});
}
} else {
if (botComment) {
await github.rest.issues.deleteComment({
comment_id: botComment.id,
owner: context.repo.owner,
repo: context.repo.repo
});
}
}
hadolint:
name: Hadolint Dockerfile
if: github.repository == 'kkovaletp/photoview'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Lint Dockerfile
id: hadolint
uses: hadolint/[email protected]
with:
dockerfile: Dockerfile
config: ${{ github.workspace }}/.hadolint.yaml
format: tty
failure-threshold: error
- name: Update Pull Request
uses: actions/github-script@v7
if: ${{ ( steps.hadolint.conclusion == 'success' || steps.hadolint.conclusion == 'failure' ) && github.event_name == 'pull_request' }}
with:
script: |
let hadolintResults = process.env.HADOLINT_RESULTS;
let output = '';
const comments = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo
});
const botComment = comments.data.find(
comment => comment.user.login === 'github-actions[bot]'
&& comment.body.includes('Hadolint')
);
if (hadolintResults) {
output += '#### Hadolint issues:\n';
output += 'Hadolint detected issues during execution.\n';
output += '\n```\n' + hadolintResults + '\n```\n';
output += '\nFind more info about detected issues and recommendations for fixes in the ';
output += '[Rules table](https://github.com/hadolint/hadolint?tab=readme-ov-file#rules).';
if (botComment) {
await github.rest.issues.updateComment({
comment_id: botComment.id,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
});
} else {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
});
}
} else {
if (botComment) {
await github.rest.issues.deleteComment({
comment_id: botComment.id,
owner: context.repo.owner,
repo: context.repo.repo
});
}
}
- name: Generate report
uses: hadolint/[email protected]
id: hadolint-report
if: always()
with:
dockerfile: Dockerfile
config: ${{ github.workspace }}/.hadolint.yaml
output-file: hadolint.sarif
format: sarif
failure-threshold: ignore
- name: Upload report
uses: github/codeql-action/upload-sarif@v3
if: ${{ steps.hadolint-report.conclusion == 'success' || steps.hadolint-report.conclusion == 'failure' }}
with:
sarif_file: hadolint.sarif
coverity:
name: Coverity Scan
runs-on: ubuntu-22.04
if: github.repository == 'kkovaletp/photoview' && github.event_name != 'pull_request'
env:
COV_PROJECT: kkovaletp%2Fphotoview
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Fetch branches
shell: bash
run: git fetch --all
- name: Set up Go
uses: actions/setup-go@v5
id: go
with:
go-version: '~1.21.13' # Temporary hardcode Go version, as Coverity doesn't support latest Go
cache: false
# Temporary w/a until newer GO version is not supported by Coverity
- name: Modify go.mod for CI
run: |
sed -i 's/^go [0-9]\+\.[0-9]\+\(\.[0-9]\+\)\?/go 1.21/' api/go.mod
- name: Cache Go dependencies
uses: actions/cache@v4
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Get C dependencies
shell: bash
run: |
sudo add-apt-repository ppa:strukturag/libheif
sudo add-apt-repository ppa:strukturag/libde265
sudo apt-get update
sudo apt-get install -y libdlib-dev libblas-dev libatlas-base-dev liblapack-dev libjpeg-turbo8-dev libheif-dev
- name: Get GO dependencies
shell: bash
working-directory: api
run: |
go get -v -t -d ./...
if [ -f Gopkg.toml ]; then
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
dep ensure
fi
# Coverity steps are based on the https://github.com/vapier/coverity-scan-action/blob/main/action.yml
# and the https://github.com/vapier/coverity-scan-action/pull/3/files
# The Coverity site says the tool is usually updated twice yearly, so the
# md5 of download can be used to determine whether there's been an update.
- name: Lookup Coverity Build Tool hash
id: coverity-cache-lookup
shell: bash
run: |
echo "hash=$(curl https://scan.coverity.com/download/other/linux64 \
--data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=${{ env.COV_PROJECT }}&md5=1")" >> $GITHUB_OUTPUT
# Try to cache the tool to avoid downloading 1GB+ archive on every run.
# Cache miss will add ~30s to create, but cache hit will save minutes.
- name: Cache Coverity Analysis Tool
id: cov-analysis-cache
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/cov-analysis
key: cov-analysis-linux64-${{ steps.coverity-cache-lookup.outputs.hash }}
# Download and unpack the binaries, configure to use our GO compiler
- name: Install Coverity Analysis Tool
if: steps.cov-analysis-cache.outputs.cache-hit != 'true'
shell: bash
run: |
curl https://scan.coverity.com/download/other/linux64 \
--no-progress-meter \
--output cov-analysis.tar.gz \
--data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=${{ env.COV_PROJECT }}"
mkdir ./cov-analysis
tar -xzf ./cov-analysis.tar.gz --strip 1 -C ./cov-analysis
rm ./cov-analysis.tar.gz
export PATH="${{ github.workspace }}/cov-analysis/bin:${PATH}"
cov-configure --comptype go --compiler $(which go)
# Register Coverity executables in system PATH
- name: Add Coverity Analysis Tool to PATH
shell: bash
run: |
echo "${{ github.workspace }}/cov-analysis/bin" >> $GITHUB_PATH
# Build and capture API code
# At this moment Coverity doesn't support GO 1.22, so ignoring build failures
- name: Build API with cov-build
shell: bash
working-directory: api
run: |
cov-build --dir ${{ github.workspace }}/cov-int \
--return-emit-failures \
--fs-capture-search ./ go build -v . || (\
cat ${{ github.workspace }}/cov-int/build-log.txt && \
exit 1 \
)
- name: Setup Node.js 18
uses: actions/setup-node@v4
with:
node-version: 18
cache: 'npm'
cache-dependency-path: ui/package-lock.json
- name: Install UI dependencies
shell: bash
working-directory: ui
run: npm ci --omit=dev --ignore-scripts
# Build and capture UI code
- name: Build UI with cov-build
shell: bash
working-directory: ui
run: |
cov-build --dir ${{ github.workspace }}/cov-int \
--return-emit-failures \
--fs-capture-search ./ npm run build -- --base=/ || (\
cat ${{ github.workspace }}/cov-int/build-log.txt && \
exit 1 \
)
# Run FS capture for the rest of the files in the project
- name: Scan whole project with fs-capture
shell: bash
run: |
cov-build --dir ${{ github.workspace }}/cov-int \
--return-emit-failures --no-command \
--fs-capture-search ./ || (\
cat ${{ github.workspace }}/cov-int/build-log.txt && \
exit 1 \
)
# Remove unnecessary captures from the Coverity results before sending them for analysis
# Extract 'git blame' info for captured files
- name: Prepare collected results
shell: bash
run: |
cov-manage-emit --dir ${{ github.workspace }}/cov-int \
--verbose 2 \
--tu-pattern "file('/.vscode/')" \
--tu-pattern "file('_test.go')" \
--tu-pattern "file('/node_modules/')" \
--tu-pattern "file('/testing/')" \
--tu-pattern "file('.test.tsx')" \
--tu-pattern "file('/cov-analysis/')" \
--tu-pattern "file('/cov-int/')" \
--tu-pattern "file('/home/runner/go/pkg/')" \
list
cov-manage-emit --dir ${{ github.workspace }}/cov-int \
--verbose 2 \
--tu-pattern "file('/.vscode/')" \
--tu-pattern "file('_test.go')" \
--tu-pattern "file('/node_modules/')" \
--tu-pattern "file('/testing/')" \
--tu-pattern "file('.test.tsx')" \
--tu-pattern "file('/cov-analysis/')" \
--tu-pattern "file('/cov-int/')" \
--tu-pattern "file('/home/runner/go/pkg/')" \
delete
cov-import-scm --scm git \
--dir ${{ github.workspace }}/cov-int \
--ms-delay 10 --verbose 0
# Archive and send all the results to the Coverity server
- name: Submit results to Coverity Scan
shell: bash
run: |
tar -czvf ./cov-int.tgz ./cov-int
curl \
--form token="${{ secrets.COVERITY_SCAN_TOKEN }}" \
--form email="${{ secrets.COVERITY_SCAN_EMAIL }}" \
--form [email protected] \
--form version="${{ github.sha }}" \
--form description="coverity-scan-action ${{ github.repository }} / ${{ github.ref }}" \
"https://scan.coverity.com/builds?project=${{ env.COV_PROJECT }}"