1
0
mirror of https://github.com/owncloud/ocis.git synced 2025-04-18 23:44:07 +03:00

add code coverage flag to the debug build and add docs for generating the coverage report

This commit is contained in:
Niraj Acharya 2025-03-28 12:15:08 +05:45
parent c118bada1e
commit a1df9e6716
5 changed files with 244 additions and 13 deletions

View File

@ -452,6 +452,13 @@ def main(ctx):
),
)
test_pipelines.append(
pipelineDependsOn(
uploadAPITestCoverageReport(ctx),
testPipelines(ctx),
),
)
pipelines = test_pipelines + build_release_pipelines
if ctx.build.event == "cron":
@ -742,6 +749,7 @@ def buildOcisBinaryForTesting(ctx):
makeNodeGenerate("") +
makeGoGenerate("") +
build() +
buildDebug() +
rebuildBuildArtifactCache(ctx, "ocis-binary-amd64", "ocis/bin"),
"trigger": {
"ref": [
@ -1035,7 +1043,8 @@ def localApiTestPipeline(ctx):
((wopiCollaborationService("fakeoffice") + wopiCollaborationService("collabora") + wopiCollaborationService("onlyoffice")) if params["collaborationServiceNeeded"] else []) +
(ocisHealthCheck("wopi", ["wopi-collabora:9304", "wopi-onlyoffice:9304", "wopi-fakeoffice:9304"]) if params["collaborationServiceNeeded"] else []) +
localApiTests(ctx, name, params["suites"], storage, params["extraEnvironment"], run_with_remote_php) +
logRequests(),
logRequests() +
generateCoverageFromAPITest(ctx, name),
"services": (emailService() if params["emailNeeded"] else []) +
(clamavService() if params["antivirusNeeded"] else []) +
((fakeOffice() + collaboraService() + onlyofficeService()) if params["collaborationServiceNeeded"] else []),
@ -1050,6 +1059,49 @@ def localApiTestPipeline(ctx):
pipelines.append(pipeline)
return pipelines
def generateCoverageFromAPITest(ctx, name):
environment = {
"GOCOVERDIR": "reports",
}
return [
{
"name": "coverageReport-%s" % name,
"image": OC_CI_GOLANG,
"environment": environment,
"commands": [
"go tool covdata percent -i=$GOCOVERDIR -o=coverage-%s.out" % name,
],
},
{
"name": "coverage-locate",
"image": OC_UBUNTU,
"commands": [
"mkdir -p cache/acceptance/coverage/",
"mv coverage-%s.out cache/acceptance/coverage/" % name,
],
},
{
"name": "coverage-cache-1",
"image": PLUGINS_S3,
"settings": {
"endpoint": {
"from_secret": "cache_s3_server",
},
"bucket": "cache",
"source": "cache/acceptance/coverage/coverage-%s.out" % name,
"target": "%s/%s/coverage" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"),
"path_style": True,
"access_key": {
"from_secret": "cache_s3_access_key",
},
"secret_key": {
"from_secret": "cache_s3_secret_key",
},
},
},
]
def localApiTests(ctx, name, suites, storage = "ocis", extra_environment = {}, with_remote_php = False):
test_dir = "%s/tests/acceptance" % dirs["base"]
expected_failures_file = "%s/expected-failures-localAPI-on-%s-storage.md" % (test_dir, storage.upper())
@ -1130,7 +1182,6 @@ def wopiValidatorTests(ctx, storage, wopiServerType, accounts_hash_difficulty =
"RenameFileIfCreateChildFileIsNotSupported",
]
ocis_bin = "ocis/bin/ocis"
validatorTests = []
wopiServer = []
extra_server_environment = {}
@ -1272,7 +1323,8 @@ def coreApiTests(ctx, part_number = 1, number_of_parts = 1, with_remote_php = Fa
],
},
] +
logRequests(),
logRequests() +
generateCoverageFromAPITest(ctx, part_number),
"services": redisForOCStorage(storage),
"depends_on": getPipelineNames(buildOcisBinaryForTesting(ctx)),
"trigger": {
@ -1367,7 +1419,7 @@ def e2eTestPipeline(ctx):
restoreWebCache() + \
restoreWebPnpmCache() + \
(tikaService() if params["tikaNeeded"] else []) + \
ocisServer(extra_server_environment = extra_server_environment, tika_enabled = params["tikaNeeded"])
ocisServer(extra_server_environment = extra_server_environment, tika_enabled = params["tikaNeeded"], debug = False)
step_e2e = {
"name": "e2e-tests",
@ -1515,7 +1567,7 @@ def multiServiceE2ePipeline(ctx):
restoreWebCache() + \
restoreWebPnpmCache() + \
tikaService() + \
ocisServer(extra_server_environment = extra_server_environment, tika_enabled = params["tikaNeeded"]) + \
ocisServer(extra_server_environment = extra_server_environment, tika_enabled = params["tikaNeeded"], debug = False) + \
storage_users_services + \
[{
"name": "e2e-tests",
@ -2343,7 +2395,7 @@ def notify(ctx):
},
}
def ocisServer(storage = "ocis", accounts_hash_difficulty = 4, volumes = [], depends_on = [], deploy_type = "", extra_server_environment = {}, with_wrapper = False, tika_enabled = False):
def ocisServer(storage = "ocis", accounts_hash_difficulty = 4, volumes = [], depends_on = [], deploy_type = "", extra_server_environment = {}, with_wrapper = False, tika_enabled = False, debug = True):
user = "0:0"
container_name = OCIS_SERVER_NAME
environment = {
@ -2399,6 +2451,7 @@ def ocisServer(storage = "ocis", accounts_hash_difficulty = 4, volumes = [], dep
"WEB_DEBUG_ADDR": "0.0.0.0:9104",
"WEBDAV_DEBUG_ADDR": "0.0.0.0:9119",
"WEBFINGER_DEBUG_ADDR": "0.0.0.0:9279",
"GOCOVERDIR": "reports",
}
if deploy_type == "":
@ -2443,6 +2496,8 @@ def ocisServer(storage = "ocis", accounts_hash_difficulty = 4, volumes = [], dep
environment[item] = extra_server_environment[item]
ocis_bin = "ocis/bin/ocis"
if debug:
ocis_bin = "ocis/bin/ocis-debug"
wrapper_commands = [
"make -C %s build" % dirs["ocisWrapper"],
@ -2461,6 +2516,13 @@ def ocisServer(storage = "ocis", accounts_hash_difficulty = 4, volumes = [], dep
"depends_on": depends_on,
}
commands = [
"mkdir -p $GOCOVERDIR",
"%s init --insecure true" % ocis_bin,
"cat $OCIS_CONFIG_DIR/ocis.yaml",
"cp tests/config/drone/app-registry.yaml /root/.ocis/config/app-registry.yaml",
] + (wrapper_commands)
return [
{
"name": container_name,
@ -2468,11 +2530,7 @@ def ocisServer(storage = "ocis", accounts_hash_difficulty = 4, volumes = [], dep
"detach": True,
"environment": environment,
"user": user,
"commands": [
"%s init --insecure true" % ocis_bin,
"cat $OCIS_CONFIG_DIR/ocis.yaml",
"cp tests/config/drone/app-registry.yaml /root/.ocis/config/app-registry.yaml",
] + (wrapper_commands),
"commands": commands,
"volumes": volumes,
"depends_on": depends_on,
},
@ -2505,7 +2563,7 @@ def startOcisService(service = None, name = None, environment = {}, volumes = []
"detach": True,
"environment": environment,
"commands": [
"ocis/bin/ocis %s server" % service,
"ocis/bin/ocis-debug %s server" % service,
],
"volumes": volumes,
},
@ -2538,6 +2596,19 @@ def build():
},
]
def buildDebug():
return [
{
"name": "build debug binary",
"image": OC_CI_GOLANG,
"commands": [
"retry -t 3 'make -C ocis build-debug'",
],
"environment": DRONE_HTTP_PROXY_ENV,
"volumes": [stepVolumeGo],
},
]
def skipIfUnchanged(ctx, type):
if ("full-ci" in ctx.build.title.lower() or ctx.build.event == "tag" or ctx.build.event == "cron"):
return []
@ -2736,6 +2807,75 @@ def genericCache(name, action, mounts, cache_path):
}
return step
def uploadAPITestCoverageReport(ctx):
cache_path = "%s/%s/%s" % ("cache", ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}")
sonar_env = {
"SONAR_TOKEN": {
"from_secret": "sonarcloud_acceptance_tests",
},
}
if ctx.build.event == "pull_request":
sonar_env.update({
"SONAR_PULL_REQUEST_BASE": "%s" % (ctx.build.target),
"SONAR_PULL_REQUEST_BRANCH": "%s" % (ctx.build.source),
"SONAR_PULL_REQUEST_KEY": "%s" % (ctx.build.ref.replace("refs/pull/", "").split("/")[0]),
})
return {
"kind": "pipeline",
"type": "docker",
"name": "sonarcloud",
"platform": {
"os": "linux",
"arch": "amd64",
},
"steps": [
{
"name": "sync-from-cache",
"image": MINIO_MC,
"environment": MINIO_MC_ENV,
"commands": [
"mkdir -p results",
"mc alias set cache $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY",
"mc mirror cache/$CACHE_BUCKET/%s/%s/coverage results/" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"),
],
},
{
"name": "sonarcloud-properties",
"image": OC_UBUNTU,
"commands": [
"mv sonar-project.properties sonar-project.properties.skip",
"mv tests/acceptance/sonar-project.properties sonar-project.properties",
],
},
{
"name": "sonarcloud",
"image": SONARSOURCE_SONAR_SCANNER_CLI,
"environment": sonar_env,
},
{
"name": "purge-cache",
"image": MINIO_MC,
"environment": MINIO_MC_ENV,
"commands": [
"mc alias set cache $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY",
"mc rm --recursive --force cache/$CACHE_BUCKET/%s/%s" % (ctx.repo.slug, ctx.build.commit + "-${DRONE_BUILD_NUMBER}"),
],
},
],
"trigger": {
"ref": [
"refs/heads/master",
],
"status": [
"success",
"failure",
],
},
}
def genericCachePurge(flush_path):
return {
"kind": "pipeline",

View File

@ -102,7 +102,7 @@ $(BIN)/$(EXECUTABLE): $(SOURCES)
$(GOBUILD) -v -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $@ ./cmd/$(NAME)
$(BIN)/$(EXECUTABLE)-debug: $(SOURCES)
$(GOBUILD) -v -tags '$(TAGS)' -ldflags '$(DEBUG_LDFLAGS)' -gcflags '$(GCFLAGS)' -o $@ ./cmd/$(NAME)
$(GOBUILD) -v -tags '$(TAGS)' -ldflags '$(DEBUG_LDFLAGS)' -cover -gcflags '$(GCFLAGS)' -o $@ ./cmd/$(NAME)
.PHONY: watch
watch: $(REFLEX)

View File

@ -5,6 +5,7 @@
[![Build Status](https://drone.owncloud.com/api/badges/owncloud/ocis/status.svg)](https://drone.owncloud.com/owncloud/ocis)
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=owncloud_ocis&metric=security_rating)](https://sonarcloud.io/dashboard?id=owncloud_ocis)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=owncloud_ocis&metric=coverage)](https://sonarcloud.io/dashboard?id=owncloud_ocis)
[![Acceptance Test Coverage](https://sonarcloud.io/api/project_badges/measure?project=owncloud-1_ocis_acceptance-tests&metric=coverage)](https://sonarcloud.io/summary/new_code?id=owncloud-1_ocis_acceptance-tests)
[![Go Report](https://goreportcard.com/badge/github.com/owncloud/ocis)](https://goreportcard.com/report/github.com/owncloud/ocis)
[![Go Doc](https://godoc.org/github.com/owncloud/ocis?status.svg)](http://godoc.org/github.com/owncloud/ocis)
[![oCIS docker image](https://img.shields.io/docker/v/owncloud/ocis?label=oCIS%20docker%20image&logo=docker&sort=semver)](https://hub.docker.com/r/owncloud/ocis)

View File

@ -585,3 +585,39 @@ The sample `fontsMap.json` file is located in `tests/config/drone/fontsMap.json`
"defaultFont": "/path/to/ocis/tests/config/drone/NotoSans.ttf"
}
```
## Generating Code Coverage Report by Running Acceptance Tests
To find out what oCIS code is covered by the API tests, first create a debug build of oCIS.
```shell
make -c ocis build-debug
```
oCIS should be served by the debug binary.
```shell
ocis/bin/ocis-debug server
```
Then define a folder to store the coverage report.
```shell
export GOCOVERDIR=coveragedatafiles
```
Running the tests will generate the coverage report inside the `coveragedatafiles` directory.
To view the report in human readable form, enter the following command or refer to the official [documentation](https://go.dev/doc/build-cover#working) for more formats.
```
go tool covdata textfmt -i=coveragedatafiles -o=cov.txt
```
You can also view the report in a web UI using the following command.
```
go tool cover -html=cov.txt
```
This command should open a browser with the code report.

View File

@ -0,0 +1,54 @@
sonar.projectKey=owncloud-1_ocis_acceptance-tests
sonar.organization=owncloud-1
sonar.projectVersion=7.1.1
sonar.host.url=https://sonarcloud.io
# =====================================================
# Meta-data for the project
# =====================================================
sonar.links.homepage=https://github.com/owncloud/ocis
sonar.links.ci=https://drone.owncloud.com/owncloud/ocis/
sonar.links.scm=https://github.com/owncloud/ocis
sonar.links.issue=https://github.com/owncloud/ocis/issues
# =====================================================
# Properties that will be shared amongst all modules
# =====================================================
# SQ standard properties
sonar.sources=.
# Pull Requests
sonar.pullrequest.provider=github
sonar.pullrequest.github.repository=owncloud/ocis
sonar.pullrequest.base=${env.SONAR_PULL_REQUEST_BASE}
sonar.pullrequest.branch=${env.SONAR_PULL_REQUEST_BRANCH}
sonar.pullrequest.key=${env.SONAR_PULL_REQUEST_KEY}
# Properties specific to language plugins:
sonar.go.coverage.reportPaths=results/coverage-*.out
# Exclude files
sonar.exclusions=**/third_party,docs/**,changelog/**,**/package.json,**/rollup.config.js,CHANGELOG.md,deployments/**,tests/**,vendor/**,vendor-bin/**,README.md,**/mocks/**,/protogen/**,**/*_gen.go
sonar.coverage.exclusions=**/*_test.go,**mocks/**,/protogen/**,**/*_gen.go
sonar.cpd.exclusions=**/defaultconfig.go,**/*_test.go,**/revaconfig/**,services/settings/pkg/store/defaults/defaults.go
# Rule exclusions
sonar.issue.ignore.multicriteria=g1,g2
# Ignore "Define a constant instead of duplicating this literal" rule for tests
sonar.issue.ignore.multicriteria.g1.ruleKey=go:S1192
sonar.issue.ignore.multicriteria.g1.resourceKey=**/*_test.go
# Ignore "Rename function XXX to match the regular expression ^(_|[a-zA-Z0-9]+)$" rule for tests
sonar.issue.ignore.multicriteria.g2.ruleKey=go:S100
sonar.issue.ignore.multicriteria.g2.resourceKey=**/*_test.go
# Timeout for web requests
#sonar.ws.timeout=60 is the default, but we need to increase it to deal with timeouts when loading defaults
sonar.ws.timeout=120
#
sonar.go.skipUnchanged=true
sonar.scm.forceReloadAll=true