diff --git a/hack/test-dpj/contents/metadata/identifiers.json b/hack/test-dpj/contents/metadata/identifiers.json new file mode 100644 index 00000000..41b8eae4 --- /dev/null +++ b/hack/test-dpj/contents/metadata/identifiers.json @@ -0,0 +1,11 @@ +[ + { + "file": "objects/DPJ/journal/avlxml.xml", + "identifiers": [ + { + "identifier": "2.16.578.1.39.100.11.9876.33", + "identifierType": "avleveringsidentifikator" + } + ] + } +] diff --git a/internal/nha/activities/activities.go b/internal/nha/activities/activities.go index 44ed50fb..6f8da380 100644 --- a/internal/nha/activities/activities.go +++ b/internal/nha/activities/activities.go @@ -1,3 +1,5 @@ +// Package activities implements workflow activities specific to Norway Health +// Authority. package activities var ( diff --git a/internal/nha/activities/hari.go b/internal/nha/activities/hari.go index e694b9b3..41f5fe34 100644 --- a/internal/nha/activities/hari.go +++ b/internal/nha/activities/hari.go @@ -30,6 +30,7 @@ var hariClient = &http.Client{ }, } +// UpdateHARIActivity delivers a receipt to HARI. type UpdateHARIActivity struct { manager *manager.Manager } @@ -73,7 +74,18 @@ func (a UpdateHARIActivity) Execute(ctx context.Context, params *UpdateHARIActiv return wferrors.NonRetryableError(fmt.Errorf("error reading AVLXML file: %v", err)) } - if err := a.sendRequest(ctx, blob, apiURL, params.NameInfo.Type, params); err != nil { + var parentID string + { + if params.NameInfo.Type != nha.TransferTypeAVLXML { + const idtype = "avleveringsidentifikator" + parentID, err = readIdentifier(params.FullPath, params.NameInfo.Type.String()+"/journal/avlxml.xml", idtype) + if err != nil { + return wferrors.NonRetryableError(fmt.Errorf("error looking up avleveringsidentifikator: %v", err)) + } + } + } + + if err := a.sendRequest(ctx, blob, apiURL, params.NameInfo.Type, parentID, params); err != nil { return fmt.Errorf("error sending request: %v", err) } @@ -132,13 +144,14 @@ func (a UpdateHARIActivity) url() (string, error) { return bu.ResolveReference(p).String(), nil } -func (a UpdateHARIActivity) sendRequest(ctx context.Context, blob []byte, apiURL string, kind nha.TransferType, params *UpdateHARIActivityParams) error { +func (a UpdateHARIActivity) sendRequest(ctx context.Context, blob []byte, apiURL string, kind nha.TransferType, parentID string, params *UpdateHARIActivityParams) error { payload := &avlRequest{ XML: blob, Message: fmt.Sprintf("AVLXML was processed by Archivematica pipeline %s", params.PipelineName), Type: kind.Lower(), Timestamp: avlRequestTime{params.StoredAt}, AIPID: params.SIPID, + Parent: parentID, } var buffer bytes.Buffer @@ -179,10 +192,14 @@ func (a UpdateHARIActivity) sendRequest(ctx context.Context, blob []byte, apiURL // buildMock returns a test server used when HARI's API is not available. func (a UpdateHARIActivity) buildMock() *httptest.Server { return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - a.manager.Logger.Info( + blob, _ := ioutil.ReadAll(r.Body) + defer r.Body.Close() + + a.manager.Logger.V(1).Info( "Request received", "method", r.Method, "path", r.URL.Path, + "body", string(blob), ) w.WriteHeader(http.StatusOK) @@ -190,12 +207,14 @@ func (a UpdateHARIActivity) buildMock() *httptest.Server { })) } +// avlRequest is the payload of the HTTP request delivered to HARI. type avlRequest struct { - XML []byte `json:"xml"` // AVLXML document encoded using base64. - Message string `json:"message"` // E.g.: "AVLXML was processed by DPJ Archivematica pipeline" - Type string `json:"type"` // Lowercase. E.g.: "dpj", "epj", "other" or "avlxml". - Timestamp avlRequestTime `json:"timestamp"` // E.g.: "2018-11-12T20:20:39+00:00". - AIPID string `json:"aip_id"` + XML []byte `json:"xml"` // AVLXML document encoded using base64. + Message string `json:"message"` // E.g.: "AVLXML was processed by DPJ Archivematica pipeline" + Type string `json:"type"` // Lowercase. E.g.: "dpj", "epj", "other" or "avlxml". + Timestamp avlRequestTime `json:"timestamp"` // E.g.: "2018-11-12T20:20:39+00:00". + AIPID string `json:"aip_id"` // Typically a UUID. + Parent string `json:"parent,omitempty"` // avleveringsidentifikator (only concerns DPJ and EPJ SIPs) } // avlRequestTime encodes time in JSON using the format expected by HARI. diff --git a/internal/nha/activities/hari_test.go b/internal/nha/activities/hari_test.go index 9091b2a7..fdd2c8da 100644 --- a/internal/nha/activities/hari_test.go +++ b/internal/nha/activities/hari_test.go @@ -66,12 +66,33 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{}, - dirOpts: []fs.PathOp{fs.WithDir("DPJ/journal"), fs.WithFile("DPJ/journal/avlxml.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/avlxml.xml", ""), + fs.WithDir("metadata"), + fs.WithFile("metadata/identifiers.json", `[{ + "file": "objects/DPJ/aFoobar.jpg", + "identifiers": [{ + "identifierType": "organisasjonsnummer", + "identifier": "123456789" + }] + }, { + "file": "objects/DPJ/journal/avlxml.xml", + "identifiers": [{ + "identifierType": "organisasjonsnummer", + "identifier": "123456789" + }, { + "identifierType": "avleveringsidentifikator", + "identifier": "12345" + }] + }]`), + }, wantReceipt: &avlRequest{ Message: "AVLXML was processed by Archivematica pipeline zr-fig-pipe-001", Type: "dpj", Timestamp: avlRequestTime{time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)}, AIPID: "1db240cc-3cea-4e55-903c-6280562e1866", + Parent: "12345", XML: []byte(``), }, }, @@ -86,12 +107,24 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{}, - dirOpts: []fs.PathOp{fs.WithDir("EPJ/journal"), fs.WithFile("EPJ/journal/avlxml.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("EPJ/journal"), + fs.WithFile("EPJ/journal/avlxml.xml", ""), + fs.WithDir("metadata"), + fs.WithFile("metadata/identifiers.json", `[{ + "file": "objects/EPJ/journal/avlxml.xml", + "identifiers": [{ + "identifierType": "avleveringsidentifikator", + "identifier": "12345" + }] + }]`), + }, wantReceipt: &avlRequest{ Message: "AVLXML was processed by Archivematica pipeline zr-fig-pipe-001", Type: "epj", Timestamp: avlRequestTime{time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)}, AIPID: "1db240cc-3cea-4e55-903c-6280562e1866", + Parent: "12345", XML: []byte(``), }, }, @@ -106,7 +139,10 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{}, - dirOpts: []fs.PathOp{fs.WithDir("AVLXML/objekter"), fs.WithFile("AVLXML/objekter/avlxml-2.16.578.1.39.100.11.9876.4-20191104.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("AVLXML/objekter"), + fs.WithFile("AVLXML/objekter/avlxml-2.16.578.1.39.100.11.9876.4-20191104.xml", ""), + }, wantReceipt: &avlRequest{ Message: "AVLXML was processed by Archivematica pipeline zr-fig-pipe-001", Type: "avlxml", @@ -126,7 +162,10 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{}, - dirOpts: []fs.PathOp{fs.WithDir("AVLXML/objekter"), fs.WithFile("AVLXML/objekter/avlxml.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("AVLXML/objekter"), + fs.WithFile("AVLXML/objekter/avlxml.xml", ""), + }, wantReceipt: &avlRequest{ Message: "AVLXML was processed by Archivematica pipeline zr-fig-pipe-001", Type: "avlxml", @@ -146,12 +185,24 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{}, - dirOpts: []fs.PathOp{fs.WithDir("OTHER/journal"), fs.WithFile("OTHER/journal/avlxml.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("OTHER/journal"), + fs.WithFile("OTHER/journal/avlxml.xml", ""), + fs.WithDir("metadata"), + fs.WithFile("metadata/identifiers.json", `[{ + "file": "objects/OTHER/journal/avlxml.xml", + "identifiers": [{ + "identifierType": "avleveringsidentifikator", + "identifier": "12345" + }] + }]`), + }, wantReceipt: &avlRequest{ Message: "AVLXML was processed by Archivematica pipeline zr-fig-pipe-001", Type: "other", Timestamp: avlRequestTime{time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)}, AIPID: "1db240cc-3cea-4e55-903c-6280562e1866", + Parent: "12345", XML: []byte(``), }, }, @@ -166,12 +217,24 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{}, - dirOpts: []fs.PathOp{fs.WithDir("DPJ/Journal"), fs.WithFile("DPJ/Journal/avlxml.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/Journal"), + fs.WithFile("DPJ/Journal/avlxml.xml", ""), + fs.WithDir("metadata"), + fs.WithFile("metadata/identifiers.json", `[{ + "file": "objects/DPJ/Journal/avlxml.xml", + "identifiers": [{ + "identifierType": "avleveringsidentifikator", + "identifier": "12345" + }] + }]`), + }, wantReceipt: &avlRequest{ Message: "AVLXML was processed by Archivematica pipeline zr-fig-pipe-001", Type: "dpj", Timestamp: avlRequestTime{time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)}, AIPID: "1db240cc-3cea-4e55-903c-6280562e1866", + Parent: "12345", XML: []byte(``), }, }, @@ -186,12 +249,24 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{}, - dirOpts: []fs.PathOp{fs.WithDir("DPJ/journal"), fs.WithFile("DPJ/journal/avlxml.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/avlxml.xml", ""), + fs.WithDir("metadata"), + fs.WithFile("metadata/identifiers.json", `[{ + "file": "objects/DPJ/journal/avlxml.xml", + "identifiers": [{ + "identifierType": "avleveringsidentifikator", + "identifier": "12345" + }] + }]`), + }, wantReceipt: &avlRequest{ Message: "AVLXML was processed by Archivematica pipeline zr-fig-pipe-001", Type: "dpj", Timestamp: avlRequestTime{time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)}, AIPID: "1db240cc-3cea-4e55-903c-6280562e1866", + Parent: "12345", XML: []byte(``), }, }, @@ -206,7 +281,65 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{"mock": true}, - dirOpts: []fs.PathOp{fs.WithDir("DPJ/journal"), fs.WithFile("DPJ/journal/avlxml.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/avlxml.xml", ""), + fs.WithDir("metadata"), + fs.WithFile("metadata/identifiers.json", `[{ + "file": "objects/DPJ/journal/avlxml.xml", + "identifiers": [{ + "identifierType": "avleveringsidentifikator", + "identifier": "12345" + }] + }]`), + }, + }, + "Failure when identifiers.json is missing (DPJ/EPJ/OTHER)": { + params: UpdateHARIActivityParams{ + StoredAt: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), + SIPID: "1db240cc-3cea-4e55-903c-6280562e1866", + PipelineName: "zr-fig-pipe-001", + NameInfo: nha.NameInfo{ + Identifier: "049d6a44-07d6-4aa9-9607-9347ec4d0b23", + Type: nha.TransferTypeDPJ, + }, + }, + hariConfig: map[string]interface{}{}, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/avlxml.xml", ""), + }, + wantErr: testutil.ActivityError{ + NRE: true, + }, + }, + "Failure when identifier cannot be found (DPJ/EPJ/OTHER)": { + params: UpdateHARIActivityParams{ + StoredAt: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), + SIPID: "1db240cc-3cea-4e55-903c-6280562e1866", + PipelineName: "zr-fig-pipe-001", + NameInfo: nha.NameInfo{ + Identifier: "049d6a44-07d6-4aa9-9607-9347ec4d0b23", + Type: nha.TransferTypeDPJ, + }, + }, + hariConfig: map[string]interface{}{}, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/avlxml.xml", ""), + fs.WithDir("metadata"), + fs.WithFile("metadata/identifiers.json", `[{ + "file": "objects/DPJ/journal/avlxml.xml", + "identifiers": [{ + "identifierType": "not-the-identifier-we-wanted", + "identifier": "12345" + }] + }]`), + }, + wantErr: testutil.ActivityError{ + Message: "error looking up avleveringsidentifikator: error reading identifier: not found", + NRE: true, + }, }, "Failure when HARI returns a server error": { params: UpdateHARIActivityParams{ @@ -218,14 +351,26 @@ func TestHARIActivity(t *testing.T) { Type: nha.TransferTypeDPJ, }, }, - hariConfig: map[string]interface{}{}, - dirOpts: []fs.PathOp{fs.WithDir("DPJ/journal"), fs.WithFile("DPJ/journal/avlxml.xml", "")}, + hariConfig: map[string]interface{}{}, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/avlxml.xml", ""), + fs.WithDir("metadata"), + fs.WithFile("metadata/identifiers.json", `[{ + "file": "objects/DPJ/journal/avlxml.xml", + "identifiers": [{ + "identifierType": "avleveringsidentifikator", + "identifier": "12345" + }] + }]`), + }, wantResponse: &serverResponse{code: 500, status: "Backend server not available, try again later."}, wantReceipt: &avlRequest{ Message: "AVLXML was processed by Archivematica pipeline zr-fig-pipe-001", Type: "dpj", Timestamp: avlRequestTime{time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)}, AIPID: "1db240cc-3cea-4e55-903c-6280562e1866", + Parent: "12345", XML: []byte(``), }, wantErr: testutil.ActivityError{ @@ -243,7 +388,10 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{"baseURL": "http://192.168.1.50:12345"}, - dirOpts: []fs.PathOp{fs.WithDir("DPJ/journal"), fs.WithFile("DPJ/journal/_____other_name_____.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/_____other_name_____.xml", ""), + }, wantErr: testutil.ActivityError{ Message: "error reading AVLXML file: not found", NRE: true, @@ -259,10 +407,12 @@ func TestHARIActivity(t *testing.T) { }, }, hariConfig: map[string]interface{}{"baseURL": string([]byte{0x7f})}, - dirOpts: []fs.PathOp{fs.WithDir("DPJ/journal"), fs.WithFile("DPJ/journal/avlxml.xml", "")}, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/avlxml.xml", ""), + }, wantErr: testutil.ActivityError{ - Message: fmt.Sprintf("error in URL construction: error looking up baseURL configuration attribute: parse %s/: net/url: invalid control character in URL", string(0x7f)), - NRE: true, + NRE: true, }, }, } diff --git a/internal/nha/activities/identifiers.go b/internal/nha/activities/identifiers.go new file mode 100644 index 00000000..16209a9e --- /dev/null +++ b/internal/nha/activities/identifiers.go @@ -0,0 +1,63 @@ +package activities + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "path/filepath" + "strings" +) + +// TransferIdentifiers is the type that maps to the JSON-encoded document found +// in Archivematica transfers to list identifiers. +type TransferIdentifiers []TransferIdentifier + +type TransferIdentifier struct { + File string `json:"file"` + Identifiers []TransferIdentifierPair `json:"identifiers"` +} + +type TransferIdentifierPair struct { + // avleveringsidentifikator is the one we want + Type string `json:"identifierType"` + Value string `json:"identifier"` +} + +// readIdentifiers returns the identifiers found in the given transfer path. +func readIdentifiers(path string) (TransferIdentifiers, error) { + identifiers := TransferIdentifiers([]TransferIdentifier{}) + + blob, err := ioutil.ReadFile(filepath.Join(path, "metadata", "identifiers.json")) + if err != nil { + return nil, err + } + + if err := json.Unmarshal(blob, &identifiers); err != nil { + return nil, err + } + + return identifiers, nil +} + +// readIdentifier returns the specified identifier found in the given transfer +// path. file matching uses case-insensitive suffix matching. +func readIdentifier(path string, fileSuffix string, idtype string) (string, error) { + identifiers, err := readIdentifiers(path) + if err != nil { + return "", fmt.Errorf("error reading identifier: %v", err) + } + + for _, item := range identifiers { + if !strings.HasSuffix(strings.ToLower(item.File), strings.ToLower(fileSuffix)) { + continue + } + for _, pair := range item.Identifiers { + if pair.Type == idtype { + return pair.Value, nil + } + } + } + + return "", errors.New("error reading identifier: not found") +} diff --git a/internal/nha/activities/prod.go b/internal/nha/activities/prod.go index 55572b0e..fe99d80d 100644 --- a/internal/nha/activities/prod.go +++ b/internal/nha/activities/prod.go @@ -31,6 +31,7 @@ type UpdateProductionSystemActivityParams struct { StoredAt time.Time PipelineName string NameInfo nha.NameInfo + FullPath string } func (a *UpdateProductionSystemActivity) Execute(ctx context.Context, params *UpdateProductionSystemActivityParams) error { @@ -55,8 +56,19 @@ func (a *UpdateProductionSystemActivity) Execute(ctx context.Context, params *Up return wferrors.NonRetryableError(fmt.Errorf("error creating receipt file: %v", err)) } + var parentID string + { + if params.NameInfo.Type != nha.TransferTypeAVLXML { + const idtype = "avleveringsidentifikator" + parentID, err = readIdentifier(params.FullPath, params.NameInfo.Type.String()+"/journal/avlxml.xml", idtype) + if err != nil { + return wferrors.NonRetryableError(fmt.Errorf("error looking up avleveringsidentifikator: %v", err)) + } + } + } + // Write receipt contents. - if err := a.generateReceipt(params, file); err != nil { + if err := a.generateReceipt(params, file, parentID); err != nil { return wferrors.NonRetryableError(fmt.Errorf("error writing receipt file: %v", err)) } @@ -75,13 +87,14 @@ func (a *UpdateProductionSystemActivity) Execute(ctx context.Context, params *Up return nil } -func (a UpdateProductionSystemActivity) generateReceipt(params *UpdateProductionSystemActivityParams, file *os.File) error { +func (a UpdateProductionSystemActivity) generateReceipt(params *UpdateProductionSystemActivityParams, file *os.File, parentID string) error { receipt := prodSystemReceipt{ Identifier: params.NameInfo.Identifier, Type: params.NameInfo.Type.Lower(), Accepted: true, Message: fmt.Sprintf("Package was processed by Archivematica pipeline %s", params.PipelineName), Timestamp: params.StoredAt, + Parent: parentID, } enc := json.NewEncoder(file) @@ -98,9 +111,10 @@ func (a UpdateProductionSystemActivity) generateReceipt(params *UpdateProduction } type prodSystemReceipt struct { - Identifier string `json:"identifier"` // Original identifier. - Type string `json:"type"` // Lowercase. E.g. "dpj", "epj", "other" or "avlxml". - Accepted bool `json:"accepted"` // Whether we have an error during processing. - Message string `json:"message"` // E.g. "Package was processed by Archivematica pipeline am" or any other error message. - Timestamp time.Time `json:"timestamp"` // RFC3339, e.g. "2006-01-02T15:04:05Z07:00" + Identifier string `json:"identifier"` // Original identifier. + Type string `json:"type"` // Lowercase. E.g. "dpj", "epj", "other" or "avlxml". + Accepted bool `json:"accepted"` // Whether we have an error during processing. + Message string `json:"message"` // E.g. "Package was processed by Archivematica pipeline am" or any other error message. + Timestamp time.Time `json:"timestamp"` // RFC3339, e.g. "2006-01-02T15:04:05Z07:00" + Parent string `json:"parent,omitempty"` // avleveringsidentifikator (only concerns DPJ and EPJ SIPs) } diff --git a/internal/nha/activities/prod_test.go b/internal/nha/activities/prod_test.go index 9804785b..cd07f8d1 100644 --- a/internal/nha/activities/prod_test.go +++ b/internal/nha/activities/prod_test.go @@ -32,6 +32,7 @@ func TestProdActivity(t *testing.T) { tests := map[string]struct { params UpdateProductionSystemActivityParams hookConfig *map[string]interface{} + dirOpts []fs.PathOp wantContent string wantErr testutil.ActivityError }{ @@ -44,11 +45,46 @@ func TestProdActivity(t *testing.T) { Type: nha.TransferTypeDPJ, }, }, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/avlxml.xml", ""), + fs.WithDir("metadata"), + fs.WithFile("metadata/identifiers.json", `[{ + "file": "objects/DPJ/journal/avlxml.xml", + "identifiers": [{ + "identifierType": "avleveringsidentifikator", + "identifier": "12345" + }] + }]`), + }, wantContent: `{ "identifier": "aa1df25d-1477-4085-8be3-a17fed20f843", "type": "dpj", "accepted": true, "message": "Package was processed by Archivematica pipeline foo-bar-001", + "timestamp": "2009-11-10T23:00:00Z", + "parent": "12345" +} +`, + }, + "Receipt does not include parentID in AVLXML SIP": { + params: UpdateProductionSystemActivityParams{ + StoredAt: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), + PipelineName: "foo-bar-001", + NameInfo: nha.NameInfo{ + Identifier: "aa1df25d-1477-4085-8be3-a17fed20f843", + Type: nha.TransferTypeAVLXML, + }, + }, + dirOpts: []fs.PathOp{ + fs.WithDir("DPJ/journal"), + fs.WithFile("DPJ/journal/avlxml.xml", ""), + }, + wantContent: `{ + "identifier": "aa1df25d-1477-4085-8be3-a17fed20f843", + "type": "avlxml", + "accepted": true, + "message": "Package was processed by Archivematica pipeline foo-bar-001", "timestamp": "2009-11-10T23:00:00Z" } `, @@ -93,6 +129,10 @@ func TestProdActivity(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() + transferDir := fs.NewDir(t, "enduro", tc.dirOpts...) + defer transferDir.Remove() + tc.params.FullPath = transferDir.Path() + tmpdir := fs.NewDir(t, "enduro") defer tmpdir.Remove() hookConfig := map[string]interface{}{"receiptPath": tmpdir.Path()} diff --git a/internal/nha/doc.go b/internal/nha/doc.go new file mode 100644 index 00000000..1fea6b5a --- /dev/null +++ b/internal/nha/doc.go @@ -0,0 +1,2 @@ +// Package nha includes solutions that are specific to Norway Health Authority. +package nha diff --git a/internal/testutil/activity.go b/internal/testutil/activity.go index f5ebf59b..07d70970 100644 --- a/internal/testutil/activity.go +++ b/internal/testutil/activity.go @@ -85,5 +85,8 @@ func (ae ActivityError) assertNonRetryableError(t *testing.T, err error) { var result string perr := err.(*cadence.CustomError) assert.NilError(t, perr.Details(&result)) - assert.Equal(t, result, ae.message()) + + if ae.message() != "" { + assert.Equal(t, result, ae.message()) + } } diff --git a/internal/workflow/receipts.go b/internal/workflow/receipts.go index 762a01f7..93a0705a 100644 --- a/internal/workflow/receipts.go +++ b/internal/workflow/receipts.go @@ -53,6 +53,7 @@ func (w *ProcessingWorkflow) sendReceipts(ctx workflow.Context, params *sendRece StoredAt: params.StoredAt, PipelineName: params.PipelineName, NameInfo: params.NameInfo, + FullPath: params.FullPath, }).Get(ctx, nil) if err != nil { diff --git a/internal/workflow/receipts_test.go b/internal/workflow/receipts_test.go index 4d00ff45..164789de 100644 --- a/internal/workflow/receipts_test.go +++ b/internal/workflow/receipts_test.go @@ -121,6 +121,7 @@ func TestSendReceipts(t *testing.T) { StoredAt: params.StoredAt, PipelineName: params.PipelineName, NameInfo: params.NameInfo, + FullPath: params.FullPath, }, ).Return(nil).Once()