| service | codedeploy | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| sdk_module | aws-sdk-go-v2/service/codedeploy@v1.37.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| last_audit_commit | 59ab8f6a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| last_audit_date | 2026-07-23 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| overall | A | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ops |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| families |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gaps |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| deferred |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| leaks |
|
-
Protocol: awsjson1.1, single POST endpoint,
X-Amz-Target: CodeDeploy_20141006.<Op>dispatch viaRouteMatcher/ExtractOperationin handler.go. Verified every op inGetSupportedOperations()has adispatchTable()entry and is reachable — no stub registrations, no ops silently dropped. -
Epoch-seconds timestamp bug (the big one this pass): every
Timestampshape in CodeDeploy's model (createTime,completeTime,registerTime,deregisterTime, and thecreateTimeRange.start/endrequest filter) is serialized by the real SDK as an epoch-seconds JSON number (smithytime.FormatEpochSeconds/ parsed withsmithytime.ParseEpochSeconds— confirmed by readingaws-sdk-go-v2/service/codedeploy@v1.37.0/deserializers.goandserializers.godirectly). The handler was usingtime.Time.UnixMilli()(epoch milliseconds,int64) for every response timestamp andtime.UnixMilli()to parse the request-side range filter — a 1000x wire-format mismatch in both directions. Fixed by switching every timestamp field tofloat64and usingpkgs/awstime.Epoch()for output / a smallepochSecondsToTimehelper (mirrors thesecretsmanagerpackage'stime.Unix(0, int64(sec*float64(time.Second)))pattern) for input. Proven with a real-SDK-client round-trip test (handler_sdk_roundtrip_test.go) rather than just unit-level JSON assertions, since a scale-wrong-but-well-typed number silently decodes to a garbagetime.Timeinstead of erroring — exactly the kind of bug unit tests miss (see parity-principles.md rule 3). -
StopDeploymentOutput.status is a different enum than Deployment.status: real AWS's
StopStatusenum is only ever"Pending"or"Succeeded"— it describes the outcome of the stop request itself (this backend performs it synchronously, so always"Succeeded"). The Deployment's own resulting lifecycle status ("Stopped") is a completely separate field returned byGetDeployment. The handler was previously reusingstatusStoppedfor both, which is not a validStopStatusvalue and would fail real SDK unmarshaling into thetypes.StopStatustype in strict validation paths. This is a "looks-right-but-is-wrong" trap: don't re-flagGetDeploymentreturning"Stopped"after a stop — that part was and remains correct. -
ErrOnPremisesInstanceNotFoundsentinel had the wrong error code baked in ("InstanceNameRequiredException", which is actually a different real AWS exception for a missing/empty instance name) and noerrorMappingsentry at all, so any not-found lookup on an on-premises instance (GetOnPremisesInstance,DeregisterOnPremisesInstance) fell through to the generic 500ServiceExceptionbranch regardless of the sentinel's own code — the exact "missing errCodeLookup entry" bug class called out in parity-principles.md rule 2. Fixed the sentinel's code toInstanceDoesNotExistException(confirmed againsttypes.InstanceDoesNotExistExceptionin the real SDK) and added theerrorMappingsrow. -
SkipWaitTimeForInstanceTerminationandPutLifecycleEventHookExecutionStatusskipped the deployment-existence check every sibling deployment-scoped op (GetDeploymentInstance,GetDeploymentTarget,ListDeploymentInstances,ListDeploymentTargets,ContinueDeployment,StopDeployment) performs viah.Backend.GetDeployment(...). Both previously returned 200 OK for a nonexistentdeploymentId. Fixed to match the sibling pattern; real AWS returnsDeploymentDoesNotExistExceptionin both cases. -
Deliberate simplification, not a bug:
CreateDeploymentsetsStatus: "Succeeded"andCompleteTime: now + 5simmediately at creation time rather than modeling a genuineCreated → Queued → InProgress → Succeededprogression over time.ListDeployments' status filter andStopDeployment's transition to"Stopped"both work correctly against this synchronous model. Don't re-flag this as a "stuck deployment" bug — it's the opposite problem (instant-complete, not stuck), and every consumer-visible field derived from it (deploymentOverview, status filters) is internally consistent. -
DeleteResourcesByExternalIdempty-envelope return is correct, not a stub: this backend has no external-id-linked-resource tracking anywhere (nothing populates it), and the real AWS operation itself is a best-effort async cleanup with no required side effect visible to the caller synchronously. This is the "void-result op" pattern from parity-principles.md rule 4, not a disguised no-op. -
ApplicationRevision family de-stubbed (this pass):
RegisterApplicationRevision,GetApplicationRevision,ListApplicationRevisions, andBatchGetApplicationRevisionspreviously had no backing store at all —RegisterApplicationRevisionvalidated the application existed and then discarded the revision, soGetApplicationRevisionechoed the request straight back,ListApplicationRevisionsalways returned an empty list, andBatchGetApplicationRevisionsechoed each requested revision with no real lookup. Added anapplicationRevisions *store.Table[ApplicationRevision]keyed byappName + "\x00" + canonical-JSON(RevisionLocation)(applicationRevisionKeyin store_setup.go — twoRevisionLocationvalues with identical fields always produce the same key, matching how real CodeDeploy deduplicates revision registrations) with abyApplicationindex. Registered directly onb.registryas a "clean" table (no live*tags.Tagsfield, no DTO wrapper needed — see persistence.go's dirty-table doc comment).CreateDeploymentnow callstouchApplicationRevisionForDeployment, which auto-registers an unseen revision (real CodeDeploy auto-registers revisions supplied directly toCreateDeployment) and stampsFirstUsedTime/LastUsedTime/DeploymentGroups— the last of which also removes the deployment group from every other revision of the same application, since a deployment group targets exactly one revision at a time.DeleteApplication/UpdateApplicationgaineddeleteApplicationRevisions/renameApplicationRevisionscascades so no ghost revision rows survive an app delete or outlive an app rename under the old name. Wire shapes (genericRevisionInfo/revisionInfo/revisionLocationfield names,GenericRevisionInfo'sregisterTime/firstUsedTime/lastUsedTimeas epoch-secondsfloat64) verified againstaws-sdk-go-v2/service/codedeploy@v1.37.0/deserializers.go'sawsAwsjson11_deserializeDocumentGenericRevisionInfo/...RevisionInfoand proven with a real SDK-client round trip (Test_SDKRoundTrip_ApplicationRevision_EpochSeconds). New sentinelErrRevisionNotFound→RevisionDoesNotExistException, 404 (confirmed againsttypes.RevisionDoesNotExistException). -
Deployment-instance/target family de-stubbed (this pass):
GetDeploymentInstance,GetDeploymentTarget,ListDeploymentInstances,ListDeploymentTargets,BatchGetDeploymentInstances, andBatchGetDeploymentTargetspreviously fabricated aSucceededrecord for literally any requested ID (Get*/Batch*) or always returned an empty list (List*), regardless of whether that ID (or any target at all) actually existed. Added(b *InMemoryBackend) deploymentTargets(d *Deployment) []DeploymentTargetRecord(deployment_instances.go), computed on read from the deployment's owning deployment group's real configuration rather than persisted as a separate table (so it always reflects current on-premises instance/tag state, and needs no snapshot-version bump): forComputePlatform == "Server", oneinstanceTargetper registered, non-deregistered on-premises instance whose tags satisfy the deployment group'sOnPremisesInstanceTagFilters/OnPremisesTagSet(newmatchesOnPremisesTargeting/matchesTagSetGroupshelpers in on_premises_instances.go); for"ECS", oneecsTargetperECSServicesentry (clusterName/serviceNameas the deterministicTargetID); for"Lambda", exactly onelambdaTargetkeyed by the deployment ID itself (real CodeDeploy Lambda/ECS deployments always have exactly one and, respectively,len(ECSServices)targets — confirmed againsttypes.DeploymentTargetListSizeExceededException's doc comment). Every target'sStatusis derived from the deployment's own currentStatusviatargetStatusForDeployment(Succeeded/Failed/Skipped/InProgress) instead of a hardcoded literal that ignored what actually happened to the deployment (e.g. a stopped deployment's targets now correctly reportSkipped, proven byTestDeploymentTargets_StatusTracksDeploymentStatus).Get*/GetDeploymentTargeton an unresolvable ID now returns the newErrDeploymentTargetNotFound→DeploymentTargetDoesNotExistException(404) sentinel instead of fabricating a match;Batch*silently omits unresolvable IDs, matching this codebase's established Batch* convention (BatchGetApplicationsetc.).DeploymentTargetunion wire shape (deploymentTargetTypePascalCase enum valuesInstanceTarget/ECSTarget/LambdaTarget, nestedinstanceTarget/ecsTarget/lambdaTargetmember field names,lastUpdatedAtas epoch-secondsfloat64) verified againstawsAwsjson11_deserializeDocumentDeploymentTarget/...InstanceTarget/...ECSTarget/...LambdaTargetand proven with a real SDK-client round trip (Test_SDKRoundTrip_DeploymentTarget_EpochSeconds). KNOWN, DOCUMENTED LIMITATION: this backend has no live EC2 instance registry, soEc2TagFilters/Ec2TagSetresolve zero targets — only the on-premises side of"Server"targeting is modeled (see gaps). -
Two banned
//nolint:gocognit,cyclop,funlenremoved via decomposition (this pass):dgToOutput/dgInputFromWirein handler_deployment_groups.go were single ~130-line functions doing wire-format conversion for every optional deployment-group sub-structure (load balancer info, blue/green config, alarms, auto-rollback, EC2/on-premises tag sets) inline. Split each into onedgXToOutput/dgXFromWirehelper per sub-structure (7 helpers each direction); the top-level functions now just assemble the struct literal and loop over the flat slice fields, with zero behavior change (proven by the existingdeployment_groups_test.gosuite passing unmodified). One more banned//nolint:gocognitremoved frommatchesTagFiltersin on_premises_instances.go by extracting the per-filterKEY_ONLY/VALUE_ONLY/default switch intomatchesOneTagFilter(also fixed its comment, which incorrectly called the default case "EQUALS" — the realTagFilterTypeenum value isKEY_AND_VALUE, confirmed againsttypes.TagFilterTypein enums.go; the code was already correct, only the comment was wrong). All three were the full set of banned nolints flagged for this service —grep -rnE 'nolint:[a-z,]*(cyclop|gocyclo|gocognit|funlen)' services/codedeploy/now returns empty.