Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #2

Merged
merged 13 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
128 changes: 128 additions & 0 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
name: Build and SonarQube Analysis
on:
pull_request:
branches:
# - dev # when working with a development seat of sonarServer
- main
push:
branches:
# - dev # when working with a development seat of sonarServer
- main

jobs:
build-and-test:
runs-on: macos-latest
env:
PORT: 4201
APP_PORT: 4200

steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Set Up Node.js
uses: actions/setup-node@v3
with:
node-version: 20.16.0

- name: Install Dependencies
run: |
echo "\nInstalling dependencies\n\n"
npm ci

- name: Run Translation Validation
run: |
echo "\nRunning translation validation\n\n"
cd tests/translation && npx ts-node translation-validation.ts

- name: Build the Client
run: |
echo "\nBuilding the client\n\n"
cd client && npm run build

- name: Run Server Tests
run: |
echo "\nRunning server tests\n\n"
cd server && npm test

- name: Run Client Tests
run: |
echo "\nRunning client tests\n\n"
cd client && npm test

# #e2e Tests
# TODO uncomment once testcafe works with chrome latest
# - name: Start Angular server
# run: npm run prod &

# - name: Wait for Angular server to start
# run: |
# until curl --output /dev/null --silent --head --fail http://localhost:4200; do
# echo 'Waiting for Angular server...'
# sleep 5
# done

# - name: Run E2E Tests
# run: |
# echo "\nRunning e2e tests\n\n"
# cd tests/e2e && node clean_screenshots && node test_runner

# - name: Run Screenshot Diff Tests
# run: |
# echo "\nRunning screenshot diff tests\n\n"
# cd tests/e2e && npx testcafe-blink-diff screenshots --compare accepted:tested --open --threshold 0.003
sonarqube:
name: SonarQube
runs-on: macos-latest
needs: build-and-test # Waits for 'build-and-test' to complete
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0 # Disable shallow clone for better analysis relevance

- name: Install SonarScanner
run: |
curl -sSLo sonar-scanner-cli.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.2.1.4610-macosx-aarch64.zip
unzip -q sonar-scanner-cli.zip -d $HOME/sonar-scanner
echo "$HOME/sonar-scanner/sonar-scanner-6.2.1.4610-macosx-aarch64/bin" >> $GITHUB_PATH

- name: Run SonarScanner
run: |
sonar-scanner \
-Dsonar.projectKey=TheGameKnave_angular-boilerplate \
-Dsonar.organization=thegameknave \
-Dsonar.host.url=https://sonarcloud.io
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

- name: Wait for Quality Gate
run: |
TASK_ID=$(cat .scannerwork/report-task.txt | grep ceTaskId | cut -d= -f2)
echo "Fetching task status... for $TASK_ID"
curl -s -u "${{ secrets.SONAR_TOKEN }}:" "https://sonarcloud.io/api/ce/task?id=$TASK_ID" -o task.json

echo "Task API Response:"
cat task.json

STATUS=$(grep -o '"status":"[^"]*"' task.json | cut -d: -f2 | tr -d '"')
if [[ "$STATUS" != "SUCCESS" ]]; then
echo "Analysis did not complete successfully!"
exit 1
fi

echo "Fetching Quality Gate status..."
ANALYSIS_ID=$(grep -o '"analysisId":"[^"]*"' task.json | cut -d: -f2 | tr -d '"')
curl -s -u "${{ secrets.SONAR_TOKEN }}:" "https://sonarcloud.io/api/qualitygates/project_status?analysisId=$ANALYSIS_ID" -o gate.json

echo "Quality Gate API Response:"
cat gate.json

GATE_STATUS=$(jq -r '.projectStatus.status' gate.json)
if [[ "$GATE_STATUS" != "OK" ]]; then
echo "Quality Gate failed!"
exit 1
fi

echo "Quality Gate passed successfully!"
shell: bash
40 changes: 0 additions & 40 deletions .github/workflows/testcafe.yml

This file was deleted.

12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ This repo is intended to allow spooling up Angular projects in a monorepo rapidl
* Internationalization (i18n) with Transloco
* IndexedDB for offline storage *
* e2e testing with TestCafe + snapshots
* Feature flags *
* CI/CD (github actions, sonar)
* Hotjar script for user behavior analysis

(* indicates a feature that’s visible in the sample app)

## Future features:
* CI/CD (jenkins, sonar, etc?)
* Google Analytics reports on site activity
* Feature flags *
* public api with GraphQL *
* Websockets to reconcile disparities between server and local data *
* DB caching for external requests AND similar DB api calls (solr or the like)
* Ionic & Electron integration
* DB-agnostic query layer
* Elf state management *
* Immutable.js to minimize mutation
* Websockets to reconcile disparities between server and local data *
* Ionic & Electron integration
* Auth-agnostic (or maybe just Firebase) user management (emails and password resetting and deliverability) *

## Quick start
Expand Down
5 changes: 1 addition & 4 deletions client/src/app/components/features/features.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,9 @@ export class FeaturesComponent implements OnInit, OnDestroy {
});

this.features$.subscribe(features => {
console.log('Features emitted:', features);
Object.keys(features).forEach((feature) => {
console.log(`Checking feature: ${feature}`,this.featureControls.hasOwnProperty(feature), this.featureControls[feature].value, features[feature]);
if (this.featureControls.hasOwnProperty(feature) && this.featureControls[feature].value !== features[feature]) {
console.log(`Updating FormControl for feature: ${feature}`);
(this.featureControls[feature] as FormControl).setValue(features[feature]);
this.featureControls[feature].setValue(features[feature]);
}
});
});
Expand Down
2 changes: 1 addition & 1 deletion client/src/assets/styles/base/_typography.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body {
font-feature-settings: "lnum";
h1 {
font-weight: 600;
};
}
h2,
h3,
h4,
Expand Down
18 changes: 17 additions & 1 deletion client/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,24 @@
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-ABCDEFGH');</script>
})(window,document,'script','dataLayer','GTM-<ABCDEFGH>');</script>
<!-- End Google Tag Manager -->
<!-- Hotjar Tracking Code -->
<script>
(function (c, s, q, u, a) {
c.hj = c.hj || function () {
c.hj.q = c.hj.q || [];
c.hj.q.push(arguments);
};
c._hjSettings = { hjid: a };
const headElement = s.getElementsByTagName('head')[0];
const scriptElement = s.createElement('script');
scriptElement.async = true;
scriptElement.src = q + c._hjSettings.hjid + u;
headElement.appendChild(scriptElement);
})(window, document, 'https://static.hj.contentsquare.net/c/csq-', '.js', 12345678);
</script>
<!-- End Hotjar Tracking Code -->
<script>
window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', '<GOOGLE_TAG>');
</script>
Expand Down
2 changes: 1 addition & 1 deletion client/src/main.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { importProvidersFrom, inject, isDevMode } from '@angular/core';
import { importProvidersFrom, isDevMode } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ServiceWorkerModule } from '@angular/service-worker';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
Expand Down
15 changes: 6 additions & 9 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# SonarQube project configuration file

# Project settings
sonar.projectKey=angular-boilerplate
# SonarCloud project settings
sonar.projectKey=TheGameKnave_angular-boilerplate
sonar.organization=thegameknave
sonar.projectName=Angular Boilerplate
sonar.projectVersion=1.0

Expand All @@ -10,15 +9,13 @@ sonar.host.url=http://localhost:9000

# Source code settings
sonar.sources=.

# Exclusions
sonar.exclusions=**/vendors/**,**/tests/**,**/environments/**

# Test files
sonar.tests=tests/
sonar.test.inclusions=**/*.spec*
sonar.javascript.lcov.reportPaths=client/coverage/lcov.info,server/coverage/lcov.info

# Exclusions (adjust paths as needed)
sonar.exclusions=**/vendors/**,**/tests/**,**/environments/**,**/karma.conf.js,**/transloco.config.ts

# Rule settings
sonar.issue.ignore.multicriteria=e1
sonar.issue.ignore.multicriteria.e1.ruleKey=typescript:S1186
Expand Down
38 changes: 27 additions & 11 deletions tests/SonarQube.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
FROM eclipse-temurin:17-jre-jammy
FROM eclipse-temurin:17-jre-noble

LABEL io.k8s.description="SonarQube is a self-managed, automatic code review tool that systematically helps you deliver Clean Code."
LABEL io.openshift.min-cpu=400m
LABEL io.openshift.min-memory=2048M
LABEL io.openshift.non-scalable=true
LABEL io.openshift.tags=sonarqube,static-code-analysis,code-quality,clean-code
LABEL org.opencontainers.image.url=https://github.com/SonarSource/docker-sonarqube

ENV LANG='en_US.UTF-8' \
Expand All @@ -9,21 +14,30 @@ ENV LANG='en_US.UTF-8' \
#
# SonarQube setup
#
ARG SONARQUBE_VERSION=9.9.6.92038
ARG SONARQUBE_ZIP_URL=https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-${SONARQUBE_VERSION}.zip
ENV JAVA_HOME='/opt/java/openjdk' \
ARG SONARQUBE_VERSION=10.8.1.101195
ARG SONARQUBE_ZIP_URL=https://binaries.sonarsource.com/CommercialDistribution/sonarqube-developer/sonarqube-developer-${SONARQUBE_VERSION}.zip
ENV DOCKER_RUNNING="true" \
JAVA_HOME='/opt/java/openjdk' \
SONARQUBE_HOME=/opt/sonarqube \
SONAR_VERSION="${SONARQUBE_VERSION}" \
SQ_DATA_DIR="/opt/sonarqube/data" \
SQ_EXTENSIONS_DIR="/opt/sonarqube/extensions" \
SQ_LOGS_DIR="/opt/sonarqube/logs" \
SQ_TEMP_DIR="/opt/sonarqube/temp"

# Separate stage to use variable expansion
ENV ES_TMPDIR="${SQ_TEMP_DIR}"

RUN set -eux; \
groupadd --system --gid 1000 sonarqube; \
useradd --system --uid 1000 --gid sonarqube sonarqube; \
deluser ubuntu; \
useradd --system --uid 1000 --gid 0 sonarqube; \
apt-get update; \
apt-get --no-install-recommends -y install gnupg unzip curl bash fonts-dejavu; \
apt-get --no-install-recommends -y install \
bash \
curl \
fonts-dejavu \
gnupg \
unzip; \
echo "networkaddress.cache.ttl=5" >> "${JAVA_HOME}/conf/security/java.security"; \
sed --in-place --expression="s?securerandom.source=file:/dev/random?securerandom.source=file:/dev/urandom?g" "${JAVA_HOME}/conf/security/java.security"; \
# pub 2048R/D26468DE 2015-05-25
Expand All @@ -44,11 +58,13 @@ RUN set -eux; \
rm sonarqube.zip*; \
rm -rf ${SONARQUBE_HOME}/bin/*; \
ln -s "${SONARQUBE_HOME}/lib/sonar-application-${SONARQUBE_VERSION}.jar" "${SONARQUBE_HOME}/lib/sonarqube.jar"; \
chmod -R 555 ${SONARQUBE_HOME}; \
chmod -R ugo+wrX "${SQ_DATA_DIR}" "${SQ_EXTENSIONS_DIR}" "${SQ_LOGS_DIR}" "${SQ_TEMP_DIR}"; \
apt-get remove -y gnupg unzip curl; \
chmod -R 550 ${SONARQUBE_HOME}; \
chmod -R 770 "${SQ_DATA_DIR}" "${SQ_EXTENSIONS_DIR}" "${SQ_LOGS_DIR}" "${SQ_TEMP_DIR}"; \
apt-get remove -y gnupg unzip; \
rm -rf /var/lib/apt/lists/*;

VOLUME ["${SQ_DATA_DIR}", "${SQ_EXTENSIONS_DIR}", "${SQ_LOGS_DIR}", "${SQ_TEMP_DIR}"]

COPY entrypoint.sh ${SONARQUBE_HOME}/docker/

WORKDIR ${SONARQUBE_HOME}
Expand All @@ -57,4 +73,4 @@ EXPOSE 9000
USER sonarqube
STOPSIGNAL SIGINT

ENTRYPOINT ["/opt/sonarqube/docker/entrypoint.sh"]
ENTRYPOINT ["/opt/sonarqube/docker/entrypoint.sh"]
1 change: 0 additions & 1 deletion tests/e2e/clean_screenshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ async function cleanTestedScreenshots(rootDir) {

// If the directory does not contain an accepted.png file and none of its subdirectories contain an accepted.png file, remove it
if (!hasSubdirWithAccepted) {
//console.log(`removing ${path.relative(rootDir, dir)}`);
await fs.rm(dir, { recursive: true });
}
} else {
Expand Down
5 changes: 2 additions & 3 deletions tests/e2e/run/test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { waitForAngular } from 'testcafe-angular-selectors';
import * as path from 'path';
import * as fs from 'fs';
import { Selector, test } from 'testcafe';
import { ClientFunction } from 'testcafe';
import { Selector, test, ClientFunction } from 'testcafe';
import { getThreshold } from '../data/constants';
import { SUPPORTED_LANGUAGES } from '../../../client/src/app/helpers/constants';

Expand Down Expand Up @@ -40,7 +39,7 @@ const getMemory = async t => JSON.parse(
}));
//compare current memory against memory threshold
const validateMemory = (memoryVal: { jsHeapSizeLimit: number; usedJSHeapSize: number; totalJSHeapSize: number }, threshold: number) => {
const { jsHeapSizeLimit, usedJSHeapSize, totalJSHeapSize } = memoryVal;
const usedJSHeapSize = memoryVal.usedJSHeapSize;
const isMemoryLowerThanThreshold = usedJSHeapSize < threshold;
return isMemoryLowerThanThreshold;
};
Expand Down