Skip to content

Commit

Permalink
Merge branch 'main' into AB2D-6340/Upgrade_spring
Browse files Browse the repository at this point in the history
  • Loading branch information
Sadibhatla authored Oct 16, 2024
2 parents ab77804 + 9d838c7 commit 7ca89dc
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 25 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,11 @@ jobs:
docker build \
-t "${ECR_REPO_URI}:ab2d-${DEPLOYMENT_ENV}-$SHA_SHORT" \
-t "${ECR_REPO_URI}:ab2d-${DEPLOYMENT_ENV}-latest" .
# Push to special tag for promotion if this is run on a push to main
if [ "$GITHUB_REF" == "refs/heads/main" ]; then
docker tag $ECR_REPO_URI:ab2d-$DEPLOYMENT_ENV-$SHA_SHORT $ECR_REPO_URI:main-$SHA_SHORT
fi
echo "Pushing image"
docker push "${ECR_REPO_URI}" --all-tags
21 changes: 11 additions & 10 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ on:
- test
- sbx
- prod
- prod-test
- prod_test
module:
required: true
type: choice
Expand All @@ -33,16 +33,17 @@ jobs:
permissions:
contents: read
id-token: write
env:
DEPLOYMENT_ENV: ${{ vars[format('{0}_DEPLOYMENT_ENV', inputs.environment)] }}
ACCOUNT: ${{ inputs.environment == 'prod-test' && 'prod' || inputs.environment }}

steps:
- name: Assume role in AB2D ${{ env.ACCOUNT }} account
uses: aws-actions/configure-aws-credentials@v3
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
env:
ACCOUNT: ${{ inputs.environment == 'prod_test' && 'prod' || inputs.environment }}
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: arn:aws:iam::${{ secrets[format('{0}_ACCOUNT_ID', env.ACCOUNT)] }}:role/delegatedadmin/developer/ab2d-${{ env.ACCOUNT }}-github-actions

- name: Deploy latest image in ECR to ECS
run: aws ecs update-service --cluster ab2d-${DEPLOYMENT_ENV}-${{ inputs.module }} --service ab2d-${DEPLOYMENT_ENV}-${{ inputs.module }} --force-new-deployment
- name: Deploy ECS service to run on latest image in ECR
env:
SERVICE_NAME: ab2d-${{ vars[format('{0}_DEPLOYMENT_ENV', inputs.environment)] }}-${{ inputs.module }}
run: |
echo "Deploying service $SERVICE_NAME"
aws ecs update-service --cluster "$SERVICE_NAME" --service "$SERVICE_NAME" --force-new-deployment > /dev/null
aws ecs wait services-stable --cluster "$SERVICE_NAME" --services "$SERVICE_NAME"
60 changes: 60 additions & 0 deletions .github/workflows/promote.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: promote

on:
workflow_call:
inputs:
environment:
required: true
type: string
module:
required: true
type: string
workflow_dispatch:
inputs:
environment:
required: true
type: choice
options:
- sbx
- prod
- prod_test
module:
required: true
type: choice
options:
- api
- worker

permissions:
contents: read
id-token: write

jobs:
promote:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: arn:aws:iam::${{ secrets.MGMT_ACCOUNT_ID }}:role/delegatedadmin/developer/ab2d-mgmt-github-actions
- name: Retag images in ECR
env:
DEPLOYMENT_ENV: ${{ vars[format('{0}_DEPLOYMENT_ENV', inputs.environment)] }}
ECR_REPO_DOMAIN: ${{ secrets.MGMT_ACCOUNT_ID }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com
ECR_REPO: ab2d_${{ inputs.module }}
run: |
SHA_SHORT="$(git rev-parse --short HEAD)"
TOKEN="$(aws ecr get-authorization-token --output text --query 'authorizationData[].authorizationToken')"
CONTENT_TYPE="application/vnd.docker.distribution.manifest.v2+json"
echo "Getting the manifest of the image tagged main-$SHA_SHORT"
MANIFEST="$(curl -sS -H "Authorization: Basic $TOKEN" -H "Accept: $CONTENT_TYPE" "https://$ECR_REPO_DOMAIN/v2/$ECR_REPO/manifests/main-$SHA_SHORT")"
SHA_TAG="ab2d-$DEPLOYMENT_ENV-$SHA_SHORT"
echo "Adding the $SHA_TAG tag to main-$SHA_SHORT image"
curl -sS -X PUT -H "Authorization: Basic $TOKEN" -H "Content-Type: $CONTENT_TYPE" -d "$MANIFEST" "https://$ECR_REPO_DOMAIN/v2/$ECR_REPO/manifests/$SHA_TAG"
LATEST_TAG="ab2d-$DEPLOYMENT_ENV-latest"
echo "Adding the $LATEST_TAG tag to main-$SHA_SHORT image"
curl -sS -X PUT -H "Authorization: Basic $TOKEN" -H "Content-Type: $CONTENT_TYPE" -d "$MANIFEST" "https://$ECR_REPO_DOMAIN/v2/$ECR_REPO/manifests/$LATEST_TAG"
46 changes: 46 additions & 0 deletions .github/workflows/push-main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: push to main

on:
push:
branches:
- main

jobs:
build-api:
uses: ./.github/workflows/build.yml
with:
environment: test
module: api
secrets: inherit
build-worker:
uses: ./.github/workflows/build.yml
with:
environment: test
module: worker
secrets: inherit
deploy-api:
needs: build-api
permissions:
contents: read
id-token: write
uses: ./.github/workflows/deploy.yml
with:
environment: test
module: api
secrets: inherit
deploy-worker:
needs: build-worker
permissions:
contents: read
id-token: write
uses: ./.github/workflows/deploy.yml
with:
environment: test
module: worker
secrets: inherit
e2e-test:
needs: [deploy-api, deploy-worker]
uses: ./.github/workflows/e2e-test.yml
with:
environment: test
secrets: inherit
89 changes: 89 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: release

on:
release:
types: [released]
workflow_dispatch:

permissions:
contents: read
id-token: write

jobs:
# Promote and Deploy to prod-test, which only includes worker
promote-prod-test-worker:
uses: ./.github/workflows/promote.yml
with:
environment: prod_test
module: worker
secrets: inherit

deploy-prod-test-worker:
needs: promote-prod-test-worker
uses: ./.github/workflows/deploy.yml
with:
environment: prod_test
module: worker
secrets: inherit

# Promote and Deploy to prod
promote-prod-api:
uses: ./.github/workflows/promote.yml
with:
environment: prod
module: api
secrets: inherit

promote-prod-worker:
uses: ./.github/workflows/promote.yml
with:
environment: prod
module: worker
secrets: inherit

deploy-prod-api:
needs: promote-prod-api
uses: ./.github/workflows/deploy.yml
with:
environment: prod
module: api
secrets: inherit

deploy-prod-worker:
needs: promote-prod-worker
uses: ./.github/workflows/deploy.yml
with:
environment: prod
module: worker
secrets: inherit

# Promote and Deploy to sandbox
promote-sbx-api:
uses: ./.github/workflows/promote.yml
with:
environment: sbx
module: api
secrets: inherit

promote-sbx-worker:
uses: ./.github/workflows/promote.yml
with:
environment: sbx
module: worker
secrets: inherit

deploy-sbx-api:
needs: promote-sbx-api
uses: ./.github/workflows/deploy.yml
with:
environment: sbx
module: api
secrets: inherit

deploy-sbx-worker:
needs: promote-sbx-worker
uses: ./.github/workflows/deploy.yml
with:
environment: sbx
module: worker
secrets: inherit
10 changes: 6 additions & 4 deletions .github/workflows/unit-integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0 # Get entire history for SonarQube

- name: Setup Java
uses: actions/setup-java@v3
Expand Down Expand Up @@ -54,10 +56,10 @@ jobs:
run: |
mvn -ntp -U clean
- name: SonarQube analysis
- name: Run unit and integration tests
run: |
mvn -ntp -s settings.xml ${RUNNER_DEBUG:+"--debug"} compile sonar:sonar -Dsonar.projectKey=ab2d-project -Dsonar.qualitygate.wait=true -DskipTests -Dusername=${ARTIFACTORY_USER} -Dpassword=${ARTIFACTORY_PASSWORD} -Drepository_url=${ARTIFACTORY_URL}
mvn -ntp -s settings.xml ${RUNNER_DEBUG:+"--debug"} -Dusername=${ARTIFACTORY_USER} -Dpassword=${ARTIFACTORY_PASSWORD} -Drepository_url=${ARTIFACTORY_URL} test -pl common,job,coverage,api,worker
- name: Run unit and integration tests
- name: SonarQube analysis
run: |
mvn -ntp -s settings.xml ${RUNNER_DEBUG:+"--debug"} -Dusername=${ARTIFACTORY_USER} -Dpassword=${ARTIFACTORY_PASSWORD} -Drepository_url=${ARTIFACTORY_URL} test -pl common,job,coverage,api,worker
mvn -ntp -s settings.xml ${RUNNER_DEBUG:+"--debug"} package sonar:sonar -Dsonar.projectKey=ab2d-project -Dsonar.qualitygate.wait=true -DskipTests -Dusername=${ARTIFACTORY_USER} -Dpassword=${ARTIFACTORY_PASSWORD} -Drepository_url=${ARTIFACTORY_URL}
4 changes: 2 additions & 2 deletions api/src/main/java/gov/cms/ab2d/api/config/OpenAPIConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public OpenApiCustomizer defaultResponseMessages() {
@JsonPropertyOrder({
"text"
})
static class Details {
public static class Details {

@JsonProperty("text")
private String text;
Expand Down Expand Up @@ -177,7 +177,7 @@ public void setAdditionalProperty(String name, Object value) {
"code",
"details"
})
static class Issue {
public static class Issue {
@JsonProperty("severity")
private String severity;
@JsonProperty("code")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package gov.cms.ab2d.api.controller.common;

import gov.cms.ab2d.api.config.OpenAPIConfig;
import gov.cms.ab2d.api.controller.JobCompletedResponse;
import gov.cms.ab2d.api.controller.JobProcessingException;
import gov.cms.ab2d.api.controller.TooManyRequestsException;
Expand All @@ -11,6 +12,7 @@
import gov.cms.ab2d.eventclient.events.ApiResponseEvent;
import gov.cms.ab2d.job.dto.JobPollResult;
import gov.cms.ab2d.job.model.JobOutput;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
Expand All @@ -25,14 +27,14 @@
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;


import static gov.cms.ab2d.api.controller.common.ApiText.X_PROG;
import static gov.cms.ab2d.common.util.Constants.FHIR_PREFIX;
import static gov.cms.ab2d.common.util.Constants.JOB_LOG;
import static gov.cms.ab2d.common.util.Constants.ORGANIZATION;
import static gov.cms.ab2d.common.util.Constants.REQUEST_ID;
import static org.springframework.http.HttpHeaders.EXPIRES;
import static org.springframework.http.HttpHeaders.RETRY_AFTER;
import static org.springframework.http.MediaType.APPLICATION_JSON;

@Service
@Slf4j
Expand All @@ -41,13 +43,16 @@ public class StatusCommon {
private final JobClient jobClient;
private final SQSEventClient eventLogger;
private final int retryAfterDelay;
private final OpenAPIConfig openApi;

StatusCommon(PdpClientService pdpClientService, JobClient jobClient,
SQSEventClient eventLogger, @Value("${api.retry-after.delay}") int retryAfterDelay) {
this.pdpClientService = pdpClientService;
this.jobClient = jobClient;
this.eventLogger = eventLogger;
this.retryAfterDelay = retryAfterDelay;

this.openApi = new OpenAPIConfig();
}

public void throwFailedResponse(String msg) {
Expand Down Expand Up @@ -80,6 +85,8 @@ public ResponseEntity doStatus(String jobUuid, HttpServletRequest request, Strin
"Job in progress", jobPollResult.getProgress() + "% complete",
(String) request.getAttribute(REQUEST_ID)));
return new ResponseEntity<>(null, responseHeaders, HttpStatus.ACCEPTED);
case CANCELLED:
return getCanceledResponse(jobPollResult, jobUuid, request);
case FAILED:
throwFailedResponse("Job failed while processing");
break;
Expand Down Expand Up @@ -117,6 +124,31 @@ protected JobCompletedResponse getJobCompletedResponse(JobPollResult jobPollResu
return resp;
}

protected ResponseEntity<OpenAPIConfig.OperationOutcome> getCanceledResponse(JobPollResult jobPollResult, String jobUuid, HttpServletRequest request) {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(APPLICATION_JSON);

OpenAPIConfig.OperationOutcome outcome = openApi.new OperationOutcome();
outcome.setResourceType("OperationOutcome");

OpenAPIConfig.Details details = new OpenAPIConfig.Details();
details.setText("Job is canceled.");

OpenAPIConfig.Issue issue = new OpenAPIConfig.Issue();
issue.setDetails(details);
issue.setCode("deleted");
issue.setSeverity("error");

List<OpenAPIConfig.Issue> issuesList = new ArrayList<>();
issuesList.add(issue);
outcome.setIssue(issuesList);

eventLogger.sendLogs(new ApiResponseEvent(MDC.get(ORGANIZATION), jobUuid, HttpStatus.NOT_FOUND,
"Job was previously canceled", null, (String) request.getAttribute(REQUEST_ID)));

return new ResponseEntity<OpenAPIConfig.OperationOutcome>(outcome, responseHeaders, HttpStatus.NOT_FOUND);
}

private String getUrlPath(String jobUuid, String filePath, HttpServletRequest request, String apiPrefix) {
return Common.getUrl(apiPrefix + FHIR_PREFIX + "/Job/" + jobUuid + "/file/" + filePath, request);
}
Expand Down
Loading

0 comments on commit 7ca89dc

Please sign in to comment.