api-cookbook icon indicating copy to clipboard operation
api-cookbook copied to clipboard

[Bug]: Import fails with long titles

Open semperos opened this issue 9 months ago • 2 comments

Do I have the most recent api-cookbook code?

  • [x] I am using the latest code available on the main branch of the api-cookbook repo.

Is there an existing issue for this?

  • [x] I have searched the existing issues.

Current Behavior

An import with Pivotal Tracker stories with titles that exceed 512 characters fails.

Expected Behavior

An import with Pivotal Tracker stories with titles that exceed 512 characters should succeed, truncating the original title.

Minimal Reproducible Example

TODO

Environment

  • Operating system:
  • Python/JavaScript version:

Further Information

No response

semperos avatar Feb 10 '25 13:02 semperos

Development notes:

Shortcut puts different length limits on different entities:

Field Length limit
Story name 512
Epic name 2048
Iteration name 256
Label name 1024

Furthermore, the service that validates these lengths runs on the JVM and thus uses Java's String class to perform the length check on the string. This length check (see link in the table above) returns a count of code points specific to how Java stores Unicode code points given its 16-bit representation.

In practice, this means there is the following discrepancy:

Language String String 'length'
Python "test亂" 5
Java "test亂" 5
Python "test👍" 5
Java "test👍" 6

In order for this importer to correctly truncate the names with length limits, the bytes of the Python string need to be interrogated to determine the "Java length" of the string, and then the string needs to be truncated such that Unicode characters aren't corrupted in the final truncated string.

semperos avatar Feb 21 '25 01:02 semperos

Adding this for others in the Pivotal Exodus, a quick script to find the rows. It's quicker to update the export than to patch the importer

path = '<redacted>/api-cookbook/pivotal-import/data/pivotal_export.csv'
spreadsheet = Roo::Spreadsheet.open(path)
sheet = spreadsheet.sheet(0)
titles = sheet.column(2)
titles.each.with_index { |title, index| puts "Index #{index}" if title.length > 500 }; nil

kluzny avatar Mar 04 '25 01:03 kluzny