diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 17ec244f..59225718 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -21,6 +21,7 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: + 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' @@ -33,8 +34,10 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - - OS: [e.g. MacOS, Windows, Linux ] - - Version [e.g. 10] + +- OS: [e.g. MacOS, Windows, Linux \] +- Version [e.g. 10] **Additional context** -Add any other context about the problem here. Consider environment variables, IDE (+ version), framework version, runtime version, command and parameters of execution. +Add any other context about the problem here. Consider environment variables, +IDE (+ version), framework version, runtime version, command and parameters of execution. diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 967205fa..ae9dde19 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -8,28 +8,127 @@ on: # yamllint disable-line rule:truthy pull_request: branches: ["main"] +env: + IMAGE_NAME: algorithm-exercises-ts + ARTIFACT_NAME: algorithm-exercises-ts_${{ github.sha }} + jobs: build: - name: "Build & Test in Docker" + name: "Build Docker images" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: "LINT: Build and push" + uses: docker/build-push-action@v6 + with: + context: . + target: lint + outputs: | + type=docker,dest=/tmp/${{ env.ARTIFACT_NAME }}_lint.tar + tags: | + ${{ env.IMAGE_NAME }}:lint + - name: "LINT: Upload artifact" + uses: actions/upload-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_lint + path: /tmp/${{ env.ARTIFACT_NAME }}_lint.tar + + - name: "TEST: Build and push" + uses: docker/build-push-action@v6 + with: + context: . + target: testing + outputs: | + type=docker,dest=/tmp/${{ env.ARTIFACT_NAME }}_test.tar + tags: | + ${{ env.IMAGE_NAME }}:test + - name: "TEST: Upload artifact" + uses: actions/upload-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_test + path: /tmp/${{ env.ARTIFACT_NAME }}_test.tar + + - name: "PRODUCTION: Build and push" + uses: docker/build-push-action@v6 + with: + context: . + target: production + outputs: | + type=docker,dest=/tmp/${{ env.ARTIFACT_NAME }}_prod.tar + tags: | + ${{ env.IMAGE_NAME }}:latest + ${{ env.IMAGE_NAME }}:${{ github.sha }} + - name: "PRODUCTION: Upload artifact" + uses: actions/upload-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_prod + path: /tmp/${{ env.ARTIFACT_NAME }}_prod.tar + + lint: + name: "Run in docker: LINT" + runs-on: ubuntu-latest + needs: build + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_lint + path: /tmp/ + - name: Load image + run: | + docker load --input /tmp/${{ env.ARTIFACT_NAME }}_lint.tar + docker image ls -a + + - name: Run lint + run: | + docker run --rm ${{ env.IMAGE_NAME }}:lint make lint + + test: + name: "Run in docker: TEST" runs-on: ubuntu-latest + needs: build + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_test + path: /tmp/ + + - name: Load image + run: | + docker load --input /tmp/${{ env.ARTIFACT_NAME }}_test.tar + docker image ls -a + - name: Run test + run: | + docker run --rm ${{ env.IMAGE_NAME }}:test make test + + security: + name: "Snyk Container" + runs-on: ubuntu-latest + needs: build + permissions: + actions: read + contents: read + security-events: write steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - - name: Build the Docker image - run: make compose/rebuild - - name: Lint in Docker image - run: make compose/lint - - name: Test in Docker image - run: make compose/test - - name: Run in Docker image - run: make compose/run - - name: Tag Docker image - run: > - docker tag - algorithm-exercises-ts:latest - algorithm-exercises-ts:${{ github.sha }} + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_prod + path: /tmp/ + + - name: Load image + run: | + docker load --input /tmp/${{ env.ARTIFACT_NAME }}_prod.tar + docker image ls -a - name: Run Snyk to check Docker image for vulnerabilities # Snyk can be used to break the build when it detects vulnerabilities. @@ -44,11 +143,47 @@ jobs: # yamllint enable rule:line-length SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: - image: algorithm-exercises-ts:latest + image: ${{ env.IMAGE_NAME }}:${{ github.sha }} args: --file=Dockerfile - # yamllint disable rule:comments-indentation - # - name: Upload result to GitHub Code Scanning - # uses: github/codeql-action/upload-sarif@v2 - # with: - # sarif_file: snyk.sarif - # yamllint enable rule:comments-indentation + # yamllint disable rule:line-length + # https://github.com/github/codeql-action/issues/2187#issuecomment-2043220400 + - name: Replace security-severity undefined for license-related findings + run: | + sed -i 's/"security-severity": "undefined"/"security-severity": "0"/g' snyk.sarif + sed -i 's/"security-severity": "null"/"security-severity": "0"/g' snyk.sarif + # yamllint enable rule:line-length + - name: Upload result to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'snyk.sarif' + scan: + name: "Trivy" + runs-on: ubuntu-latest + needs: build + permissions: + actions: read + contents: read + security-events: write + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }}_prod + path: /tmp/ + + - name: Load image + run: | + docker load --input /tmp/${{ env.ARTIFACT_NAME }}_prod.tar + docker image ls -a + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@0.24.0 + with: + image-ref: ${{ env.IMAGE_NAME }}:${{ github.sha }} + format: 'sarif' + output: 'trivy-results.sarif' + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'trivy-results.sarif' diff --git a/.github/workflows/snyk-code.yml b/.github/workflows/snyk-code.yml index df32d4f7..6c607e75 100644 --- a/.github/workflows/snyk-code.yml +++ b/.github/workflows/snyk-code.yml @@ -10,7 +10,12 @@ on: # yamllint disable-line rule:truthy jobs: security: + name: Snyk Open Source (Node.js) runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write steps: - uses: actions/checkout@master - name: Run Snyk to check for vulnerabilities @@ -19,10 +24,8 @@ jobs: env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: - args: --sarif-file-output=snyk.sarif - # yamllint disable rule:comments-indentation - # - name: Upload result to GitHub Code Scanning - # uses: github/codeql-action/upload-sarif@v2 - # with: - # sarif_file: snyk.sarif - # yamllint enable rule:comments-indentation + args: --sarif-file-output=snyk-code.sarif + - name: Upload result to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'snyk-code.sarif' diff --git a/Dockerfile b/Dockerfile index 9a984de5..a026e695 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,7 @@ COPY ./CODE_OF_CONDUCT.md ${WORKDIR}/ COPY ./src ${WORKDIR}/src COPY ./package.json ${WORKDIR}/package.json COPY ./package-lock.json ${WORKDIR}/package-lock.json +COPY ./tsconfig.json ${WORKDIR}/ COPY ./Makefile ${WORKDIR}/ # code linting conf @@ -48,6 +49,10 @@ COPY ./.markdownlint.yaml ${WORKDIR}/ # yamllint conf COPY ./.yamllint ${WORKDIR}/ COPY ./.yamlignore ${WORKDIR}/ +COPY ./.gitignore ${WORKDIR}/ + +# Dependencies +RUN npm ci --verbose --ignore-scripts CMD ["make", "lint"] @@ -57,6 +62,7 @@ FROM base AS development ENV WORKDIR=/app WORKDIR ${WORKDIR} +# Code source COPY ./src ${WORKDIR}/src COPY ./package.json ${WORKDIR}/package.json COPY ./package-lock.json ${WORKDIR}/package-lock.json @@ -64,7 +70,9 @@ COPY ./Makefile ${WORKDIR}/ COPY ./tsconfig.json ${WORKDIR}/tsconfig.json COPY ./tsconfig.prod.json ${WORKDIR}/tsconfig.prod.json -RUN npm ci --verbose --ignore-scripts +# Dependencies +COPY --from=lint /app/node_modules ${WORKDIR}/node_modules + RUN ls -alh # CMD []