diff --git a/.env-template b/.env-template new file mode 100644 index 0000000..e69de29 diff --git a/.github/workflows/containerize.yml b/.github/workflows/containerize.yml index 2a10856..b6f7dbc 100644 --- a/.github/workflows/containerize.yml +++ b/.github/workflows/containerize.yml @@ -1,4 +1,4 @@ -name: 🏗️📤 Build and publish 🐳 images +name: Build and publish 🐳 images on: push: @@ -13,7 +13,7 @@ env: IMAGE_NAME: ${{ github.repository }} jobs: - build-and-push-image: + build: name: 🏗️📤 Build and push 🐳 image runs-on: ubuntu-latest permissions: @@ -51,6 +51,7 @@ jobs: type=raw,value=latest,priority=100,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} type=sha,enable=true,prefix={{branch}}-,suffix=,format=short,priority=300 type=raw,prefix={{branch}}-,value=latest,priority=200,enable=${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }} + type=raw,value={{branch}},priority=500 # Caching | https://docs.docker.com/build/ci/github-actions/cache/ - name: 🏗️📤 Build and push 🐳 image diff --git a/app/api/axe/views.py b/app/api/axe/views.py index a333796..fff68aa 100644 --- a/app/api/axe/views.py +++ b/app/api/axe/views.py @@ -127,3 +127,34 @@ def axe_domain_error_summary(): return format_output(results, output_format, 'axe_domain_error_summary') except Exception as e: return jsonify({"error": str(e)}), 500 + +# Githib Reports #15 +# https://github.com/orgs/GovA11y/projects/1?pane=issue&itemId=34493510 +@axe_bp.route('/test-summary', methods=['GET']) +def axe_summary(): + raw_domain = request.args.get('domain', 'gsa.gov') + domain = f"%{raw_domain}" + + + sql_file = "app/api/database/postgres/queries/axe/coverage.sql" + logger.info(f'Request: Test Coverage by Domain\nDomain: {raw_domain}') + + # Read sql file + with open(sql_file) as file: + sql_content = file.read() + formatted_sql_content = sql_content % domain + + results = [] + try: + # Run the query using ClickHouse's execute method + rows = clickhouse_conn.execute(formatted_sql_content, with_column_types=True) + keys = [col[0] for col in rows[1]] + for row in rows[0]: + results.append({key: value for key,value in zip(keys, row)}) + output_format = request.args.get('format', 'json') + return format_output(results, output_format, 'domain_summary') + except Exception as e: + return jsonify({"error": str(e)}), 500 + + + diff --git a/app/api/database/postgres/queries/axe/coverage.sql b/app/api/database/postgres/queries/axe/coverage.sql new file mode 100644 index 0000000..92a70ef --- /dev/null +++ b/app/api/database/postgres/queries/axe/coverage.sql @@ -0,0 +1,19 @@ +-- Test Coverage by Domain +-- app/api/database/postgres/queries/axe/coverage.sql + +SELECT + d.domain, + COUNT(u.id) AS total_urls, + COUNT(CASE WHEN u.active_scan_axe THEN 1 END) AS active_axe_urls, + COUNT(CASE WHEN u.is_objective THEN 1 END) AS is_objective_urls, + COUNT(CASE WHEN u.errored THEN 1 END) AS errored_urls, + ROUND( + 100.0 * COUNT(CASE WHEN u.active_scan_axe THEN 1 END) / NULLIF(COUNT(u.id), 0), + 2 + ) AS domain_coverage_axe +FROM targets.domains d +LEFT JOIN targets.urls u ON d.id = u.domain_id +WHERE d."domain" ILIKE '%s' +GROUP BY d.domain +ORDER BY d.domain; + diff --git a/app/api/domain/views.py b/app/api/domain/views.py index 03d9798..d226a07 100644 --- a/app/api/domain/views.py +++ b/app/api/domain/views.py @@ -136,4 +136,4 @@ def domain_add(): output_format = request.args.get('format', 'json') return format_output(results, output_format, 'domain_summary') except Exception as e: - return jsonify({"error": str(e)}), 500 \ No newline at end of file + return jsonify({"error": str(e)}), 500 diff --git a/run.py b/run.py index 34ffc5a..0650505 100644 --- a/run.py +++ b/run.py @@ -11,3 +11,5 @@ # Use the APP_PORT environment variable port = os.environ.get('APP_PORT', 8080) app.run(host='0.0.0.0', port=port, debug=True) + +