diff --git a/.gitignore b/.gitignore index f87e660..da838b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ __output/* -!__output/cv.pdf diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index b487501..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -stages: -- test -- build -- publish - -variables: - IMAGE_NAME: ${CI_REGISTRY}/${CI_PROJECT_PATH}/cv-builder - IMAGE_TAG: ${CI_COMMIT_REF_SLUG}-${CI_COMMIT_SHORT_SHA} - RELEASE_CV_FILENAME: cv-DanAnglin-${CI_COMMIT_REF_NAME}.pdf - -include: -- template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml' -- local: '/.gitlab/ci/docker-gitlab-ci.yml' -- local: '/.gitlab/ci/cv-gitlab-ci.yml' diff --git a/.gitlab/ci/cv-gitlab-ci.yml b/.gitlab/ci/cv-gitlab-ci.yml deleted file mode 100644 index a4eb331..0000000 --- a/.gitlab/ci/cv-gitlab-ci.yml +++ /dev/null @@ -1,128 +0,0 @@ ---- -#--------------------------------------------# -# Hidden job templates for CV build pipeline # -#--------------------------------------------# -.use-cv-builder: - image: ${IMAGE_NAME}:master-44f2a31c - -.cv-default-job-rules: - rules: - - when: always - -.cv-publish-job-rules: - rules: - - if: '$CI_COMMIT_REF_NAME =~ /^[0-9]{4}(.[0-9]{2}){2}$/ && $CI_PROJECT_PATH == "dananglin/cv"' - when: always - -.default-tags: - tags: - - dananglin-general - -.release-tags: - tags: - - dananglin-cv-release - -#------------------------------------# -# Visible jobs for CV build pipeline # -#------------------------------------# -test:spellcheck: - extends: - - .cv-default-job-rules - - .default-tags - - .use-cv-builder - script: - - cv-make spellcheck - stage: test - -test:pdf: - extends: - - .cv-default-job-rules - - .default-tags - - .use-cv-builder - script: - - cv-make pdf - stage: test - -build:pdf: - artifacts: - expire_in: "30 minutes" - paths: - - __output/cv.pdf - extends: - - .default-tags - - .use-cv-builder - needs: - - job: "test:spellcheck" - artifacts: false - - job: "test:pdf" - artifacts: false - rules: - - if: '$CI_MERGE_REQUEST_IID' - when: always - script: - - cv-make pdf - stage: build - -build:pdf-for-publish: - artifacts: - expire_in: "1 year" - name: cv-DanAnglin-${CI_COMMIT_REF_NAME} - paths: - - ${RELEASE_CV_FILENAME} - - build_job_id - extends: - - .cv-publish-job-rules - - .default-tags - - .use-cv-builder - needs: - - job: "test:spellcheck" - artifacts: false - - job: "test:pdf" - artifacts: false - script: - - cv-make pdf - - mv __output/cv.pdf ${RELEASE_CV_FILENAME} - - echo "${CI_JOB_ID}" > build_job_id - stage: build - -publish:pdf:online: - before_script: - - export BUILD_JOB_ID=$( cat build_job_id ) - extends: - - .cv-publish-job-rules - - .release-tags - image: registry.gitlab.com/gitlab-org/release-cli:v0.3.0 - needs: - - job: "build:pdf-for-publish" - artifacts: true - script: - - 'echo "Publishing CV for release ${CI_COMMIT_REF_NAME}"' - - > - release-cli create --name "CV - ${CI_COMMIT_REF_NAME}" - --description "CV published with the release-cli tool for version ${CI_COMMIT_REF_NAME}" - --tag-name "${CI_COMMIT_REF_NAME}" - --ref "${CI_COMMIT_REF_NAME}" - --assets-links-name "${RELEASE_CV_FILENAME}" - --assets-links-url "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${BUILD_JOB_ID}/artifacts/${RELEASE_CV_FILENAME}" - stage: "publish" - variables: - GIT_STRATEGY: "none" - -# Private releases rebuilds the CV with the extra details. -publish:pdf:private: - extends: - - .cv-publish-job-rules - - .release-tags - - .use-cv-builder - needs: - - job: "test:spellcheck" - artifacts: false - - job: "test:pdf" - artifacts: false - script: - - cv-make pdf - - mv __output/cv.pdf ${CV_DEPLOY_DIR}/${RELEASE_CV_FILENAME} - stage: publish - variables: - CV_DEPLOY_DIR: "/CV" - CV_CONTACT_PHONE: $RELEASE_CV_CONTACT_PHONE diff --git a/.gitlab/ci/docker-gitlab-ci.yml b/.gitlab/ci/docker-gitlab-ci.yml deleted file mode 100644 index 3956f2d..0000000 --- a/.gitlab/ci/docker-gitlab-ci.yml +++ /dev/null @@ -1,66 +0,0 @@ ---- -#--------------------------------------------------------# -# Hidden job templates for Docker build/publish pipeline # -#--------------------------------------------------------# -.docker-build-setup: - image: docker:19.03.12 - services: - - docker:19.03.12-dind - before_script: - - apk add --no-cache go - -.dockerfile-lint: - stage: test - image: hadolint/hadolint:v2.8.0-alpine - script: - - "hadolint docker/Dockerfile" - -.dockerbuild-test: - stage: test - extends: .docker-build-setup - -.docker-test-rules: - rules: - - changes: - - "docker/Dockerfile" - - "*.go" - when: always - - if: '$CI_COMMIT_REF_NAME =~ /^[0-9]{4}(.[0-9]{2}){2}$/' - when: never - -.docker-publish-pre-post: - stage: publish - extends: .docker-build-setup - before_script: - - apk add --no-cache go - - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} - after_script: - - docker logout ${CI_REGISTRY} - -.docker-publish-rules: - rules: - - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PROJECT_PATH == "dananglin/cv" && $CI_PIPELINE_SOURCE == "web" && $BUILD_DOCKER_IMAGE == "true"' - when: always - -#------------------------------------------------# -# Visible jobs for Docker build/publish pipeline # -#------------------------------------------------# - -test:dockerfile:lint: - extends: - - .dockerfile-lint - - .docker-test-rules - -test:docker:build: - extends: - - .dockerbuild-test - - .docker-test-rules - script: - - go run mage.go image - -publish:docker-image: - extends: - - .docker-publish-pre-post - - .docker-publish-rules - script: - - go run mage.go publishImage diff --git a/data/cv.json b/data/cv.json index a422c01..14e6bd3 100644 --- a/data/cv.json +++ b/data/cv.json @@ -1,18 +1,18 @@ { "firstName": "Dan", "lastName": "Anglin", - "jobTitle": "Platform Engineer", + "jobTitle": "DevOps Engineer", "contact": { "email": "d.n.i.anglin@gmail.com", "location": "Nottingham, UK" }, "links": { "linkedin": "https://www.linkedin.com/in/dan-anglin-0174671b7", - "gitlab": "https://gitlab.com/dananglin" + "github": "https://github.com/dananglin" }, "summary": [ "I am a strong engineering professional with over seven years of experience in Platform Automation and DevOps.", - "I enjoy working with Go, Terraform, containerisation technologies and GNU/Linux.", + "I enjoy working with Go, Kubernetes, Terraform, containerisation technologies and GNU/Linux.", "I am particularly keen on developing my skills in Go and growing as an experienced Software Engineer." ], "technologies": [ @@ -28,8 +28,7 @@ "category": "Cloud Hosting", "values": [ "AWS", - "Linode", - "Openstack" + "Linode" ] }, { @@ -41,12 +40,14 @@ ] }, { - "category": "Continuous Integration", + "category": "CI/CD", "values": [ + "Argo CD", + "Argo Workflows", + "Dagger", "Git", - "GitLab/GitLab CI", - "Jenkins", - "Nexus" + "GitLab CI", + "GitHub Actions" ] }, { @@ -79,7 +80,7 @@ "employment": [ { "company": "Adarga", - "location": "Remote", + "location": "London (Remote)", "jobTitle": "DevOps Engineer", "duration": { "start": { @@ -88,11 +89,15 @@ }, "present": "yes" }, - "details": [] + "details": [ + "Designed and built the infrastructure to host an Enterprise Graph Data Platform on EKS.", + "The infrastructure was provisioned using technologies such as Terraform, Helm, Argo CD, Argo Workflows and AWS services.", + "A typical day would include activities such as deploying improvements to Production environments with Terraform and Atlantis, and deploying or updating applications on EKS using GitHub and Argo CD." + ] }, { "company": "Experian", - "location": "Nottingham", + "location": "Nottingham (Hybrid)", "jobTitle": "Platform Engineer", "duration": { "start": { @@ -105,17 +110,17 @@ } }, "details": [ - "Gained knowledge and and experience with IAC technologies such Terraform and Helm.", - "Became a core contributor to a large Terraform project that builds EKS environments for development teams to migrate their development activities onto EKS.", + "Gained knowledge and experience with IAC technologies such Terraform and Helm.", + "Became a core contributor to a large Terraform project to build EKS environments for development teams to migrate their development activities onto EKS.", "Built a new EKS environment using the mentioned Terraform project and helped migrate a live production environment within a short time frame.", - "Currently providing support for development teams to improve their development experience on EKS by resolving platform/deployment issues and improving the Terraform project to make deploying EKS environments easier for DevOps practitioners and SREs.", - "Currently supporting Platform teams to build new production EKS environments.", - "Currently researching new capabilities that can help reduce running costs, optimise node group configuration, and ease environment management for DevOps practitioners and SREs." + "Provided support for development teams to improve their development experience on EKS by resolving platform/deployment issues and improving the Terraform project to make deploying EKS environments easier for DevOps practitioners and SREs.", + "Supported platform teams to build new production EKS environments.", + "Researched new capabilities to help reduce running costs of the EKS environments and ease environment management for DevOps practitioners and SREs." ] }, { "company": "Ocado Technology", - "location": "Hatfield, Hertfordshire", + "location": "Hatfield, Hertfordshire (Onsite)", "jobTitle": "Platform Automation Engineer", "duration": { "start": { @@ -139,7 +144,7 @@ }, { "company": "QA Consulting (Contracted to CACI)", - "location": "London", + "location": "London (Onsite)", "jobTitle": "DevOps Consultant", "duration": { "start": { @@ -162,7 +167,7 @@ }, { "company": "QA Consulting (Contracted to IBM)", - "location": "Home Office, London", + "location": "Home Office, London (Onsite)", "jobTitle": "DevOps Consultant", "duration": { "start": { @@ -184,7 +189,7 @@ }, { "company": "QA Consulting", - "location": "Worthing", + "location": "Worthing (Onsite)", "jobTitle": "Trainee DevOps Consultant", "duration": { "start": { @@ -205,7 +210,7 @@ }, { "company": "School of Systems Engineering, University of Reading", - "location": "Reading", + "location": "Reading (Onsite)", "jobTitle": "Undergraduate Researcher", "duration": { "start": { diff --git a/docker/Dockerfile b/docker/Dockerfile index 7c33665..d5e6d83 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17.6-buster AS builder +FROM golang:1.19-buster AS builder RUN git clone https://github.com/magefile/mage "${GOPATH}/src/mage" @@ -21,26 +21,25 @@ COPY --from=builder /usr/local/bin/cv-make /usr/local/bin # Install dependencies RUN \ - apt-get update && \ - apt-get install -y \ - fonts-crosextra-carlito=20130920-1 \ - rsync=3.1.3-6 \ - curl=7.64.0-4+deb10u2 \ - aspell=0.60.7~20110707-6+deb10u1 \ - aspell-en=2018.04.16-0-1 \ - && \ - apt-get clean autoclean && \ - apt-get autoremove -y && \ - rm -rf /var/lib/apt/lists/* /tmp/* && \ - mkdir /opt/context + apt-get update \ + && apt-get install -y \ + fonts-crosextra-carlito \ + rsync \ + curl= \ + aspell \ + aspell-en \ + && apt-get clean autoclean \ + && apt-get autoremove -y \ + && rm -rf /var/lib/apt/lists/* /tmp/* \ + && mkdir /opt/context WORKDIR /opt/context # Install ConTeXt standalone RUN \ - curl -LO http://minimals.contextgarden.net/setup/first-setup.sh && \ - sh first-setup.sh --context=current --engine=luatex && \ - rm -rf /opt/context/tex/texmf-context/doc + curl -LO http://minimals.contextgarden.net/setup/first-setup.sh \ + && sh first-setup.sh --context=current --engine=luatex \ + && rm -rf /opt/context/tex/texmf-context/doc ENV PATH=${PATH}:/opt/context/tex/texmf-linux-64/bin \ OSFONTDIR=/usr/share/fonts diff --git a/go.mod b/go.mod index 59642e0..292f808 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module gitlab.com/dananglin/cv -go 1.12 +go 1.19 -require github.com/magefile/mage v1.10.0 +require github.com/magefile/mage v1.14.0 diff --git a/go.sum b/go.sum index 547126d..f8bfb2f 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g= -github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= +github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= diff --git a/mage.go b/mage.go deleted file mode 100644 index a3f23b4..0000000 --- a/mage.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build ignore - -package main - -import ( - "os" - - "github.com/magefile/mage/mage" -) - -func main() { - os.Exit(mage.Main()) -} diff --git a/helpers/cv.go b/magefiles/cv.go similarity index 95% rename from helpers/cv.go rename to magefiles/cv.go index dacb52e..5348620 100644 --- a/helpers/cv.go +++ b/magefiles/cv.go @@ -1,4 +1,6 @@ -package helpers +//go:build mage + +package main type Cv struct { FirstName string `json:"firstName"` @@ -21,7 +23,7 @@ type Contact struct { type Links struct { LinkedIn string `json:"linkedin"` - GitLab string `json:"gitlab"` + GitHub string `json:"github"` } type Technologies struct { diff --git a/helpers/helpers.go b/magefiles/helpers.go similarity index 77% rename from helpers/helpers.go rename to magefiles/helpers.go index 6d86653..3e90a02 100644 --- a/helpers/helpers.go +++ b/magefiles/helpers.go @@ -1,10 +1,11 @@ -package helpers +//go:build mage + +package main import ( "encoding/json" "fmt" "io" - "io/ioutil" "os" "os/exec" "strings" @@ -17,10 +18,10 @@ const ( defaultImageTag string = "latest" ) -// ImageName generates the docker image name from the environment +// imageName generates the docker image name from the environment // variables IMAGE_NAME and IMAGE_TAG. Default vaules will be used // if these variables are not set or empty. -func ImageName() string { +func imageName() string { name := os.Getenv("IMAGE_NAME") if len(name) == 0 { name = defaultImageName @@ -34,22 +35,24 @@ func ImageName() string { return name + ":" + tag } -// CreateCVTex generates the CV docuemnt as a Tex file. -func CreateCVTex(cvJsonDataFile, cvTemplateDir, cvOutputDir, cvOutputFileName string) error { +// createCVTex generates the CV docuemnt as a Tex file. +func createCVTex(cvJsonDataFile, cvTemplateDir, cvOutputDir, cvOutputFileName string) error { fmt.Printf("INFO: Attempting to read data from %s...\n", cvJsonDataFile) - data, err := ioutil.ReadFile(cvJsonDataFile) + data, err := os.ReadFile(cvJsonDataFile) if err != nil { - return fmt.Errorf("ERROR: Unable to read data from file. %s\n", err.Error()) + return fmt.Errorf("unable to read data from file. %w", err) } + fmt.Println("INFO: Successfully read data.") fmt.Println("INFO: Attempting to unmarshal JSON data...") var cv Cv if err = json.Unmarshal(data, &cv); err != nil { - return fmt.Errorf("ERROR: Unable to unmarshal JSON data. %s\n", err.Error()) + return fmt.Errorf("unable to unmarshal JSON data; %w", err) } + fmt.Println("INFO: JSON unmarshalling was successful.") // if CV_CONTACT_PHONE is set then add it to the CV @@ -62,12 +65,12 @@ func CreateCVTex(cvJsonDataFile, cvTemplateDir, cvOutputDir, cvOutputFileName st fmt.Printf("INFO: Attempting to create output file %s...\n", cvOutputPath) if err = os.MkdirAll(cvOutputDir, 0750); err != nil { - return fmt.Errorf("ERROR: Unable to create output directory %s. %s\n", cvOutputDir, err.Error()) + return fmt.Errorf("unable to create output directory %s; %w", cvOutputDir, err) } output, err := os.Create(cvOutputPath) if err != nil { - return fmt.Errorf("ERROR: Unable to create output file %s. %s\n", cvOutputPath, err.Error()) + return fmt.Errorf("unable to create output file %s; %w", cvOutputPath, err) } fmt.Printf("INFO: Successfully created output file %s.\n", cvOutputPath) defer output.Close() @@ -82,17 +85,17 @@ func CreateCVTex(cvJsonDataFile, cvTemplateDir, cvOutputDir, cvOutputFileName st t := template.Must(template.New("cv.tmpl.tex").Funcs(fmap).Delims("<<", ">>").ParseGlob(cvTemplateDir + "*.tmpl.tex")) if err = t.Execute(output, cv); err != nil { - return fmt.Errorf("ERROR: Unable to execute the CV template. %s\n", err.Error()) + return fmt.Errorf("unable to execute the CV template. %w", err) } fmt.Println("INFO: Template execution successful.") return nil } -func SpellCheck(dataFile, aspellPersonalWordlist string) error { +func spellCheck(dataFile, aspellPersonalWordlist string) error { fmt.Printf("INFO: Reading data from %s...\n", dataFile) - data, err := ioutil.ReadFile(dataFile) + data, err := os.ReadFile(dataFile) if err != nil { return fmt.Errorf("unable to read data from %s, %s", dataFile, err.Error()) } diff --git a/magefile.go b/magefiles/mage.go similarity index 86% rename from magefile.go rename to magefiles/mage.go index 09845f4..d8ce030 100644 --- a/magefile.go +++ b/magefiles/mage.go @@ -1,4 +1,4 @@ -// +build mage +//go:build mage package main @@ -7,7 +7,6 @@ import ( "github.com/magefile/mage/mg" "github.com/magefile/mage/sh" - "gitlab.com/dananglin/cv/helpers" ) const ( @@ -27,7 +26,7 @@ var Default = Pdf // Any error found while gathering the list is returned. // This function depends on the aspell program. func SpellCheck() error { - return helpers.SpellCheck(cvJsonDataFile, aspellPersonalWordlist) + return spellCheck(cvJsonDataFile, aspellPersonalWordlist) } // Tex takes the CV data file and generates the output tex file from @@ -37,7 +36,7 @@ func Tex() error { mg.Deps(Clean) - return helpers.CreateCVTex(cvJsonDataFile, cvTemplateDir, cvOutputDir, cvOutputFileName) + return createCVTex(cvJsonDataFile, cvTemplateDir, cvOutputDir, cvOutputFileName) } // Pdf takes the output tex file generated by the Tex target and @@ -53,7 +52,7 @@ func Pdf() error { // Image builds the CV builder docker image. func Image() error { - image := helpers.ImageName() + image := imageName() return sh.Run("docker", "build", "-f", dockerfile, "-t", image, ".") } @@ -63,7 +62,7 @@ func Image() error { func PublishImage() error { mg.Deps(Image) - image := helpers.ImageName() + image := imageName() return sh.Run("docker", "push", image) } diff --git a/helpers/templatefuncs.go b/magefiles/templatefuncs.go similarity index 96% rename from helpers/templatefuncs.go rename to magefiles/templatefuncs.go index f2ac1fb..f42ad30 100644 --- a/helpers/templatefuncs.go +++ b/magefiles/templatefuncs.go @@ -1,4 +1,6 @@ -package helpers +//go:build mage + +package main import ( "fmt" diff --git a/template/tex/cv.tmpl.tex b/template/tex/cv.tmpl.tex index de8e7b5..35caa3a 100644 --- a/template/tex/cv.tmpl.tex +++ b/template/tex/cv.tmpl.tex @@ -10,7 +10,7 @@ {\bf Location:} <<.Contact.Location>>\blank[medium] <>{\bf LinkedIn:} <<.Links.LinkedIn>>\blank[none]<> - <>{\bf GitLab:} <<.Links.GitLab>>\blank[none]<> + <>{\bf GitHub:} <<.Links.GitHub>>\blank[none]<> \stoptitleAndContact \section{SUMMARY}