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

Feat/opg scanning poc #6

Merged
merged 45 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
459810e
feat/opg-scanning: initial commit of base structure
Oct 29, 2024
82ea835
feat/opg-scanning-poc: simplification of factory parser format type c…
Oct 30, 2024
0aacb5d
feat/opg-scanning-poc: refactored approach after deeper analysis of d…
Oct 30, 2024
75d44b4
feat/opg-scanning-poc: integrate centralized logging in ingestion queue.
Oct 30, 2024
6aa18e1
feat/opg-scanning-poc: job queue test implementation - added proper p…
Oct 30, 2024
d46969d
feat/opg-scanning-poc: added empty callback to avoid breaking changes..
Oct 30, 2024
0d66214
feat/opg-scanning-poc: fixed typo in readme.
Oct 30, 2024
be438d1
feat/opg-scanning-poc: added context-based managment to worker pool t…
Oct 30, 2024
60b1b9d
feat/opg-scanning-poc: implemented xsd validation / cleaned redundant…
Oct 31, 2024
ffceab1
feat/opg-scanning-poc: bug fixes and prep for test handler of api.
Nov 1, 2024
bee2d3c
feat/opg-scanning-poc: fixed config.go implementation, improved inges…
Nov 1, 2024
bc21772
feat/opg-scanning-poc: first handler test pass for xsd validation.
Nov 1, 2024
7dbd699
feat/opg-scanning-poc: updated handler_test.go.
Nov 1, 2024
53343e0
feat/opg-scanning-poc: better logging and improved config.go / added …
Nov 4, 2024
5b6082d
feat/opg-scanning-poc: removed log dir.
Nov 4, 2024
95ef026
feat/opg-scanning-poc: added parser vaidators based on struct require…
Nov 4, 2024
5cda630
Fix build pipeline
gregtyler Nov 4, 2024
c3cd52c
Set PROJECT_PATH when running tests
gregtyler Nov 4, 2024
9908c7a
feat/opg-scanning-poc: test fix for uncontrolled data used in path ex…
Nov 4, 2024
b1576fa
Merge branch 'feat/opg-scanning-poc' of https://github.com/ministryof…
Nov 4, 2024
a5b6605
feat/opg-scanning-poc: fixed a bug with logger not initalizing in job…
Nov 4, 2024
7c6af09
Fix Trivy and ECR workflow
gregtyler Nov 4, 2024
6114140
Install AWS CLI before configuring ECR
gregtyler Nov 4, 2024
625a707
Assume correct role
gregtyler Nov 4, 2024
f8d03a9
feat/opg-scanning-poc/types-refactor: initial commit of complete lpf1…
Nov 6, 2024
806e7fe
Merge branch 'feat/opg-scanning-poc' of https://github.com/ministryof…
Nov 6, 2024
e02eb8c
feat/opg-scanning-poc: refactored factory to be more extensible and m…
Nov 6, 2024
78bc329
feat/opg-scanning-poc: date validators added / document factory test
Nov 7, 2024
df72866
feat/opg-scanning-poc: clean-up.
Nov 7, 2024
29c5e33
feat/opg-scanning-poc: added alternative xml for test case and extend…
Nov 11, 2024
b99ec2c
feat/opg-scanning-poc: added common validators.
Nov 11, 2024
abd65b4
feat/opg-scanning-poc: bug fixes along with common validators impleme…
Nov 12, 2024
279c65a
feat/opg-scanning-poc: fixed issue with validation and introduced han…
Nov 12, 2024
28a765b
feat/opg-scanning-poc: fixed bug with array structures being returned…
Nov 13, 2024
47534a3
feat/opg-scanning-poc: better coverage for invalid xml example.
Nov 13, 2024
bcc11c8
feat/opg-scanning-poc: fixes against comments in PR - config.yml / RE…
Nov 15, 2024
3c943ff
feat/opg-scanning-poc: added todo to mark docs when validation fails …
Nov 15, 2024
76a3365
feat/opg-scanning-poc: lp1f validation changes for parseDate
Nov 15, 2024
834a24a
feat/opg-scanning-poc: added client.go and API handler changes to han…
Nov 15, 2024
ba26b41
feat/opg-scanning-poc: clean-up comments and provided minor fixes bas…
Nov 15, 2024
6645984
fix UID field name
gregtyler Nov 15, 2024
bf18172
Remove terraform from workflow
gregtyler Nov 15, 2024
4c32985
Fix timeout error message
gregtyler Nov 15, 2024
6706d44
Set default values on config
gregtyler Nov 15, 2024
151f688
Finish removing terraform from workflow
gregtyler Nov 15, 2024
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
126 changes: 45 additions & 81 deletions .github/workflows/_example_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,60 +19,34 @@ permissions:
repository-projects: none
statuses: none


jobs:
# generate a branch name
# generate a branch name
branch_name:
name: "Generate a safe branch name"
uses: ministryofjustice/opg-github-workflows/.github/workflows/[email protected]

# generate workspace name
workspace_name:
name: "Generate the workspace name"
uses: ministryofjustice/opg-github-workflows/.github/workflows/[email protected]

tf_version:
needs: [branch_name, workspace_name]
name: "Get terraform version"
uses: ministryofjustice/opg-github-workflows/.github/workflows/[email protected]
with:
terraform_directory: "./terraform/account/"

# LINTING
# run linting for terraform
tf_lint:
needs: [tf_version]
name: "Run terraform linting"
uses: ministryofjustice/opg-github-workflows/.github/workflows/[email protected]
with:
directory: "./terraform"
terraform_version: "${{ needs.tf_version.outputs.version}}"
terraform_wrapper: false

# tfsec for terraform
tfsec_analysis:
needs: [tf_lint]
name: "Run TFSec against the code base"
uses: ministryofjustice/opg-github-workflows/.github/workflows/[email protected]

# SAST
# codeql for pythong
# codeql for go
codeql_analysis:
name: "Run CodeQL against the code base"
uses: ministryofjustice/opg-github-workflows/.github/workflows/[email protected]
with:
application_languages: '["python"]'
application_languages: '["go"]'

# generate tag
semver_tag:
needs: [branch_name, tfsec_analysis, codeql_analysis]
needs: [branch_name, codeql_analysis]
name: "Generate the semver tag value"
uses: ministryofjustice/opg-github-workflows/.github/workflows/[email protected]
with:
branch_name: ${{ needs.branch_name.outputs.parsed }}
secrets: inherit


# Docker build, trivy scan, ECR push as a matrix
# The matrix loops over each app to build in a complicated
# structure
Expand All @@ -81,15 +55,15 @@ jobs:
name: "Docker build, trivy scan, ECR push"
runs-on: ubuntu-latest
# require all steps before this matrix to have passed
needs: [tf_version, branch_name, workspace_name, semver_tag]
needs: [branch_name, workspace_name, semver_tag]
strategy:
fail-fast: true
matrix:
# services to scan over
data:
- docker_build_directory: "./service-app"
image_app_name: "helloworld"
test_command: "ls -l"
image_app_name: "helloworld"
test_command: "go test ./..."
# we use these a few times, so its easier to generate them once and env
# vars are visible in the output, so helps with debug
env:
Expand All @@ -107,82 +81,72 @@ jobs:
working-directory: ${{ matrix.data.docker_build_directory }}
run: |
docker build -t ${{ env.local_docker_image }} .
# log in to ECR
- name: Configure AWS Credentials With Assumed Role to Management
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1
# management account role
role-to-assume: arn:aws:iam::311462405659:role/sirius-actions-ci
role-duration-seconds: 900
role-session-name: OPGScanningWorkflowGithubAction
- name: ECR Login
id: login_ecr
uses: aws-actions/[email protected]
with:
registries: 311462405659
# to check if things worked, output docker image list
- name: Docker image list
run: |
docker images
- name: Trivy scan
uses: aquasecurity/[email protected]
uses: aquasecurity/[email protected]
env:
TRIVY_DB_REPOSITORY: ${{ steps.login_ecr.outputs.registry }}/trivy-db-public-ecr/aquasecurity/trivy-db:2
TRIVY_JAVA_DB_REPOSITORY: ${{ steps.login_ecr.outputs.registry }}/trivy-db-public-ecr/aquasecurity/trivy-java-db:1
with:
image-ref: ${{ env.local_docker_image }}
severity: "HIGH,CRITICAL"
format: 'sarif'
format: "sarif"
output: ${{ env.sarif_file }}
- name: Trivy scan upload to github
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: ${{ env.sarif_file }}
# for a lot of our services, there could be a test process here
# for a lot of our services, there could be a test process here
- name: Run Tests
working-directory: ${{ matrix.data.docker_build_directory }}
env:
PROJECT_PATH: service-app
run: |
${{ matrix.data.test_command }}
######
## Push to ECR
######
- uses: unfor19/install-aws-cli-action@v1
- name: Configure AWS Credentials With Assumed Role to Management
uses: aws-actions/[email protected]
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1
# management account role
role-to-assume: arn:aws:iam::311462405659:role/gh-template-repo-ci
role-duration-seconds: 900
role-session-name: OPGExampleWorkflowGithubAction
- name: ECR Login
id: login_ecr
uses: aws-actions/[email protected]
with:
registries: 311462405659
- name: Push Container
env:
SEMVER_TAG: ${{ needs.semver_tag.outputs.tag }}
ECR_REGISTRY: ${{ steps.login_ecr.outputs.registry }}
ECR_REPOSITORY: github-template-repository/helloworld
ECR_REPOSITORY: sirius/scanning/app
run: |
docker tag ${{ env.local_docker_image }} $ECR_REGISTRY/$ECR_REPOSITORY:${{ env.SEMVER_TAG }}
docker tag ${{ env.local_docker_image }} $ECR_REGISTRY/$ECR_REPOSITORY:latest
docker push --all-tags $ECR_REGISTRY/$ECR_REPOSITORY

# example terraform build stage
terraform_account_build:
name: "Terraform Account [Apply: ${{ github.ref == 'refs/heads/main'}}]"
needs: [workspace_name, semver_tag, build_scan_push, tf_version]
uses: ministryofjustice/opg-github-workflows/.github/workflows/[email protected]
with:
terraform_version: "${{ needs.tf_version.outputs.version}}"
terraform_directory: "./terraform/account"
terraform_apply: ${{ github.ref == 'refs/heads/main' && true || false }}
# this would be replaced with the dynamic value from needs.workspace_name.output.name
# but we're just using sandbox account and single env, so use default
terraform_workspace: "default"
# normally would need some logic to decide this based on branch name etc
# - if its true we would then need to pass workspace_manager_aws_account_id &
# workspace_manager_aws_iam_role as well
is_ephemeral: false
secrets:
AWS_ACCESS_KEY_ID_ACTIONS: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY_ACTIONS: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
PAGERDUTY_TOKEN: "NONE"
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}

end:
name: 'End of workflow'
runs-on: 'ubuntu-latest'
needs: [branch_name, workspace_name, semver_tag, build_scan_push, terraform_account_build]
name: "End of workflow"
runs-on: "ubuntu-latest"
needs:
[
branch_name,
workspace_name,
semver_tag,
build_scan_push,
]
steps:
- name: "End"
run: |
echo "Done"
echo "Done"
11 changes: 11 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: '3.8'

services:
app:
build:
context: ./service-app
ports:
- "8081:8081"
environment:
- PORT=8081
command: ./app
32 changes: 28 additions & 4 deletions service-app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
FROM python:3.11.9-alpine3.20
FROM golang:1.23-alpine3.20 AS build-env

RUN apk add gcc libc-dev libxml2-dev

RUN mkdir /app
WORKDIR /app
ADD hello-world.py .

CMD ["python", "-u", "hello-world.py"]
COPY go.mod .
COPY go.sum .

RUN go mod download

COPY . .

RUN CGO_ENABLED=1 go build -a -installsuffix cgo -o /go/bin/opg-scanning /app/cmd/service

FROM alpine:3

RUN apk add libxml2-dev
ENV PROJECT_PATH=/go
ENV SIRIUS_BASE_URL=/

WORKDIR /go/bin

COPY --from=build-env /go/bin/opg-scanning main
COPY xsd /go/xsd

RUN addgroup -S app && \
adduser -S -g app app && \
chown -R app:app main
USER app
ENTRYPOINT ["./main"]
46 changes: 46 additions & 0 deletions service-app/cmd/service/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package main

import (
"context"
"os"
"os/signal"
"syscall"

"github.com/ministryofjustice/opg-go-common/telemetry"
"github.com/ministryofjustice/opg-scanning/internal/api"
)

func main() {
// Set up logging
logger := telemetry.NewLogger("opg-scanning-service")

// Initialize the tracer provider
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

shutdownTracer, err := telemetry.StartTracerProvider(ctx, logger, true)
if err != nil {
logger.Error("Failed to start tracer provider", "error", err)
return
}
defer shutdownTracer()

controller := api.NewIndexController()
controller.Queue.StartWorkerPool(ctx, 3)
logger.Info("Service started...")

go func() {
controller.HandleRequests()
}()

// Handle graceful shutdown on receiving an interrupt or SIGTERM signal
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
<-stop

// Start shutdown sequence
logger.Info("Shutting down gracefully...")
cancel()
controller.Queue.Close()
logger.Info("All jobs processed. Exiting.")
}
53 changes: 53 additions & 0 deletions service-app/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package config

import (
"log"
"path/filepath"

"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
"github.com/ministryofjustice/opg-scanning/internal/util"
)

type (
Config struct {
App App
HTTP HTTP
}

// App configuration fields.
App struct {
SiriusBaseURL string `required:"true" envconfig:"SIRIUS_BASE_URL" default:".."`
ProjectPath string `required:"true" envconfig:"PROJECT_PATH" default:".."`
ProjectFullPath string
}

// HTTP server configuration fields.
HTTP struct {
Port string `required:"true" envconfig:"HTTP_PORT" default:"8081"`
}
)

// Loads configuration from .env and environment variables.
func NewConfig() *Config {
projectRoot, err := util.GetProjectRoot()
if err != nil {
log.Fatalf("failed to get project root: %v", err)
}

envPath := filepath.Join(projectRoot, ".env")
if err := godotenv.Load(envPath); err != nil {
log.Println("No .env file found or could not be loaded. Falling back to OS environment variables.")
}

var cfg Config
if err := envconfig.Process("", &cfg); err != nil {
log.Fatalf("failed to load environment variables into config: %v", err)
}

cfg.App.ProjectFullPath = filepath.Join(projectRoot, cfg.App.ProjectPath)

log.Println("Configuration loaded successfully.")

return &cfg
}
Loading
Loading