Skip to content

Commit

Permalink
Bytt til multistage dockerfile med distroless image for å fjerne sårb…
Browse files Browse the repository at this point in the history
…arheter
  • Loading branch information
ssaegrov committed Nov 8, 2024
1 parent b2b636c commit 455c98e
Show file tree
Hide file tree
Showing 21 changed files with 252 additions and 252 deletions.
143 changes: 40 additions & 103 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,55 +1,49 @@
name: Build and deploy

on: [ push ]
name: Bygg, deploy til dev-gcp og lag release
on:
push:
branches:
- main

env:
IMAGE: ghcr.io/${{ github.repository }}:${{ github.sha }}
LATEST_IMAGE: ghcr.io/${{ github.repository }}:latest

jobs:
install:
build:
name: Bygg
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
permissions:
contents: "read"
id-token: "write"
packages: "write"
outputs:
image: ${{ steps.docker-build-push.outputs.image }}
version_tag: ${{ steps.version-tag.outputs.VERSION_TAG}}

- name: Cache node_modules
uses: actions/cache@v4
id: node_modules
with:
path: ./node_modules
key: modules-${{ hashFiles('package-lock.json') }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- uses: actions/setup-node@v4
if: steps.node_modules.outputs.cache-hit != 'true'
with:
node-version: "20.x"
cache: "npm"
registry-url: "https://npm.pkg.github.com"

- run: npm ci --ignore-scripts
if: steps.node_modules.outputs.cache-hit != 'true'
env:
NODE_AUTH_TOKEN: ${{ secrets.READER_TOKEN }}
- name: Bygg og push Docker image
uses: nais/docker-build-push@v0
id: docker-build-push
with:
team: teamdagpenger
identity_provider: ${{ secrets.NAIS_WORKLOAD_IDENTITY_PROVIDER }}
project_id: ${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}
tag: ${{ env.VERSION_TAG }}
build_secrets: NODE_AUTH_TOKEN=${{ secrets.READER_TOKEN }}
push_image: true
dockerfile: Dockerfile
docker_context: .


# test:
# needs: [ install ]
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: actions/setup-node@v4
# with:
# node-version: "20.x"
#
# - name: Cache node_modules
# uses: actions/cache@v4
# with:
# path: ./node_modules
# key: modules-${{ hashFiles('package-lock.json') }}
#
# - run: npm run test

playwright:
needs: [ install ]
timeout-minutes: 2
runs-on: ubuntu-latest
steps:
Expand All @@ -72,6 +66,9 @@ jobs:
- name: "Install dependencies"
run: npm ci --ignore-scripts
if: steps.node_modules.outputs.cache-hit != 'true'
env:
NODE_AUTH_TOKEN: ${{ secrets.READER_TOKEN }}


- name: Store Playwright's Version
run: |
Expand Down Expand Up @@ -101,73 +98,10 @@ jobs:
path: test-results/
retention-days: 7

build:
needs: [ install ]
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20.x"

- name: Cache node_modules
uses: actions/cache@v4
with:
path: ./node_modules
key: modules-${{ hashFiles('package-lock.json') }}

- run: npm run build

# Bygg docker image
- name: docker-build-push
uses: nais/docker-build-push@v0
id: docker-build-push
with:
team: teamdagpenger
push_image: true # optional, default true
dockerfile: Dockerfile # optional, default Dockerfile
docker_context: . # optional, default .
identity_provider: ${{ secrets.NAIS_WORKLOAD_IDENTITY_PROVIDER }}
project_id: ${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}

- name: Cache static files
uses: actions/cache@v4
with:
path: |
./build
./public
key: ${{ github.sha }}

upload-cdn:
needs: [ build ]
runs-on: ubuntu-latest
permissions:
contents: "read"
id-token: "write"
steps:
- uses: actions/cache@v4
id: restore-build
with:
path: |
./build
./public
key: ${{ github.sha }}
fail-on-cache-miss: true

- name: Upload static files
uses: nais/deploy/actions/cdn-upload/v2@master
with:
team: teamdagpenger
source: ./build
destination: "/dp-saksbehandling-frontend/"
identity_provider: ${{ secrets.NAIS_WORKLOAD_IDENTITY_PROVIDER }}
project_id: ${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}

deploy-dev:
if: github.ref == 'refs/heads/main'
needs: [ build, playwright, upload-cdn ]
name: Deploy til dev-gcp
needs: [ build, playwright ]
runs-on: ubuntu-latest
environment:
name: Development
Expand All @@ -176,15 +110,16 @@ jobs:
- uses: actions/checkout@v4
- uses: nais/deploy/actions/deploy@v1
env:
VAR: image=${{ needs.build.outputs.image }},githubSha=${{ github.sha }}
APIKEY: ${{ secrets.NAIS_DEPLOY_APIKEY }}
CLUSTER: dev-gcp
RESOURCE: .nais/nais.yaml,.nais/unleash-apitoken.yaml
VARS: .nais/vars-dev.yaml
PRINT_PAYLOAD: true

deploy-prod:
if: github.ref == 'refs/heads/main'
needs: [ build, playwright, upload-cdn, deploy-dev ]
name: Deploy til prod-gcp
needs: [ build, playwright, deploy-dev ]
runs-on: ubuntu-latest
environment:
name: Production
Expand All @@ -193,8 +128,10 @@ jobs:
- uses: actions/checkout@v4
- uses: nais/deploy/actions/deploy@v1
env:
VAR: image=${{ needs.build.outputs.image }},githubSha=${{ github.sha }}
APIKEY: ${{ secrets.NAIS_DEPLOY_APIKEY }}
CLUSTER: prod-gcp
RESOURCE: .nais/nais.yaml,.nais/unleash-apitoken.yaml
VARS: .nais/vars-prod.yaml
PRINT_PAYLOAD: true

47 changes: 43 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,46 @@
FROM node:20-alpine
FROM node:20-alpine as node

Check warning on line 1 in Dockerfile

View workflow job for this annotation

GitHub Actions / Bygg

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
RUN --mount=type=secret,id=NODE_AUTH_TOKEN \
npm config set //npm.pkg.github.com/:_authToken=$(cat /run/secrets/NODE_AUTH_TOKEN)
RUN npm config set @navikt:registry=https://npm.pkg.github.com


# build app
FROM node as app-build

Check warning on line 8 in Dockerfile

View workflow job for this annotation

GitHub Actions / Bygg

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
WORKDIR /app

COPY ./app ./app
COPY ./mocks ./mocks
COPY ./graphql ./graphql
COPY ./vite.config.ts ./
COPY ./package.json ./
COPY ./package-lock.json ./

RUN npm ci --ignore-scripts
RUN npm run build


# install dependencies
FROM node as app-dependencies

Check warning on line 23 in Dockerfile

View workflow job for this annotation

GitHub Actions / Bygg

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
WORKDIR /app

COPY build/ build/
COPY ./package.json ./
COPY node_modules/ node_modules/
COPY ./package-lock.json ./

RUN npm ci --ignore-scripts --omit dev


# runtime
FROM gcr.io/distroless/nodejs20-debian12 as runtime

Check warning on line 33 in Dockerfile

View workflow job for this annotation

GitHub Actions / Bygg

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
WORKDIR /app

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
ENV TZ="Europe/Oslo"
EXPOSE 3000

COPY ./public ./public/
COPY ./package.json ./package.json
COPY --from=app-build /app/build/ ./build/
COPY --from=app-dependencies /app/node_modules ./node_modules

CMD ["npm", "run" ,"start"]
CMD ["./node_modules/@remix-run/serve/dist/cli.js", "./build/server/index.js"]
5 changes: 3 additions & 2 deletions app/components/oppgave-filter-status/OppgaveFilterStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { useSearchParams } from "@remix-run/react";
import type { IOppgaveTilstand } from "~/models/oppgave.server";

const statuser: { id: IOppgaveTilstand; tekst: string }[] = [
{ id: "KLAR_TIL_KONTROLL", tekst: "Klar til kontroll" },
{ id: "UNDER_KONTROLL", tekst: "Under kontroll" },
{ id: "KLAR_TIL_BEHANDLING", tekst: "Klar til behandling" },
{ id: "UNDER_BEHANDLING", tekst: "Under behandling" },
{ id: "FERDIG_BEHANDLET", tekst: "Ferdig behandlet" },
{ id: "UNDER_KONTROLL", tekst: "Under kontroll" },
{ id: "KLAR_TIL_KONTROLL", tekst: "Til kontroll" },
{ id: "PAA_VENT", tekst: "På vent" },
{ id: "BEHANDLES_I_ARENA", tekst: "Sendt til Arena" },
];

export function OppgaveFilterStatus() {
Expand Down
15 changes: 14 additions & 1 deletion app/components/oppgave-liste/OppgaveListe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@ import styles from "./OppgaveListe.module.css";
interface IProps {
oppgaver: IListeOppgave[];
lasterOppgaver?: boolean;
visNesteOppgaveKnapp?: boolean;
visPersonIdent?: boolean;
visAntallOppgaver?: boolean;
visNesteOppgaveKnapp?: boolean;
}

export function OppgaveListe({
oppgaver,
visNesteOppgaveKnapp,
visAntallOppgaver,
lasterOppgaver,
visPersonIdent,
}: IProps) {
const { state } = useNavigation();
const location = useLocation();
Expand Down Expand Up @@ -83,6 +85,12 @@ export function OppgaveListe({
<Detail>Emne</Detail>
</Table.ColumnHeader>

{visPersonIdent && (
<Table.ColumnHeader scope="col">
<Detail>Personnummer</Detail>
</Table.ColumnHeader>
)}

<Table.ColumnHeader scope="col">
<Detail>Status</Detail>
</Table.ColumnHeader>
Expand Down Expand Up @@ -190,6 +198,9 @@ export function OppgaveListe({
</>
</Table.DataCell>

{visPersonIdent && (
<Table.DataCell>{<Detail>{oppgave.personIdent}</Detail>}</Table.DataCell>
)}
<Table.DataCell>{<Detail>{getTilstandText(tilstand)}</Detail>}</Table.DataCell>
<Table.DataCell>{<Detail>{oppgave.behandlerIdent}</Detail>}</Table.DataCell>
<Table.DataCell>{<OppgaveListeValg oppgave={oppgave} />}</Table.DataCell>
Expand Down Expand Up @@ -218,5 +229,7 @@ export function getTilstandText(tilstand: IOppgaveTilstand) {
return "Klar til kontroll";
case "UNDER_KONTROLL":
return "Under kontroll";
case "BEHANDLES_I_ARENA":
return "Sendt til Arena";
}
}
10 changes: 5 additions & 5 deletions app/entry.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import { createReadableStreamFromReadable } from "@remix-run/node";
import { isRouteErrorResponse, RemixServer } from "@remix-run/react";
import { isbot } from "isbot";
import { renderToPipeableStream } from "react-dom/server";
import { setupMockServer, startMockServer } from "../mocks/mock-server";
import { getEnv } from "./utils/env.utils";
import { logger } from "~/utils/logger.utils";
import { faro } from "@grafana/faro-core";
import { unleash } from "../unleash";
import { unleash } from "./unleash";

const ABORT_DELAY = 5000;

if (getEnv("USE_MSW") === "true") {
const server = setupMockServer();
startMockServer(server);
import("../mocks/mock-server").then(({ startMockServer }) => {
startMockServer();
});
}

const csp = {
Expand All @@ -37,7 +37,7 @@ const csp = {
};
let cspString = `connect-src ${csp["connect-src"].join(" ")}; img-src ${csp["img-src"].join(" ")};`;

if (getEnv("IS_LOCALHOST")) {
if (getEnv("IS_LOCALHOST") === "true") {
cspString =
"default-src * 'unsafe-inline' 'unsafe-eval'; script-src * blob: 'unsafe-inline' 'unsafe-eval'; connect-src * blob: 'unsafe-inline'; img-src * 'self' blob: data:; frame-src * data: blob:; style-src * 'unsafe-inline';";
}
Expand Down
11 changes: 6 additions & 5 deletions app/instrumentation.server.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
import type { OTLPExporterNodeConfigBase } from "@opentelemetry/otlp-exporter-base";
import { Resource } from "@opentelemetry/resources";
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
import { SimpleSpanProcessor } from "@opentelemetry/sdk-trace-node";
import type { OTLPGRPCExporterConfigNode } from "@opentelemetry/otlp-grpc-exporter-base";

const otelConfig = {
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
headers: {
"x-sf-service-name": "dp-saksbehandling-frontend",
},
} as OTLPExporterNodeConfigBase;
} as OTLPGRPCExporterConfigNode;

const sdk = new NodeSDK({
resource: new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: "dp-saksbehandling-frontend",
[ATTR_SERVICE_NAME]: "dp-saksbehandling-frontend",
}),
spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter(otelConfig)),
spanProcessors: [new SimpleSpanProcessor(new OTLPTraceExporter(otelConfig))],
});

sdk.start();
3 changes: 2 additions & 1 deletion app/models/oppgave.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ export type IOppgaveTilstand =
| "UNDER_BEHANDLING"
| "KLAR_TIL_KONTROLL"
| "UNDER_KONTROLL"
| "FERDIG_BEHANDLET";
| "FERDIG_BEHANDLET"
| "BEHANDLES_I_ARENA";

export async function hentOppgaver(request: Request, urlParams?: string): Promise<IListeOppgave[]> {
const onBehalfOfToken = await getSaksbehandlingOboToken(request);
Expand Down
2 changes: 1 addition & 1 deletion app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import globalCss from "~/global.css?url";
import akselOverrides from "~/aksel-overrides.css?url";
import meldingOmVedtakCss from "~/melding-om-vedtak.css?url";
import styles from "~/route-styles/root.module.css";
import { unleash } from "../unleash";
import { unleash } from "./unleash";
import { PumpkinSvg } from "~/components/halloween/PumpkinSvg";

export function meta() {
Expand Down
Loading

0 comments on commit 455c98e

Please sign in to comment.