feat(chats): add folders pinning and archive management #21
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Push a v* tag to publish installable MIDlets on a GitHub Release. | |
| # | |
| # workflow_dispatch runs the same build and uploads the artifacts, but does not | |
| # publish anything - use it to download and try the exact files a release would | |
| # contain before committing to a tag. | |
| on: | |
| push: | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| permissions: | |
| contents: write # required by softprops/action-gh-release | |
| jobs: | |
| build: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: '8' | |
| - name: Point the toolchain at JDK 8 | |
| shell: pwsh | |
| run: echo "JDK8_HOME=$env:JAVA_HOME" >> $env:GITHUB_ENV | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.x' | |
| - name: Cache pinned toolchain | |
| uses: actions/cache@v4 | |
| with: | |
| path: sdk | |
| key: sdk-${{ runner.os }}-${{ hashFiles('tools/sdk.lock.json') }} | |
| # tools/build.ps1 owns the version; the tag must agree with it. Without | |
| # this check a mistyped tag ships a JAD whose MIDlet-Version contradicts | |
| # the release it was downloaded from, and the AMS believes the JAD. | |
| - name: Resolve and verify version | |
| shell: pwsh | |
| run: | | |
| $m = Select-String -Path tools/build.ps1 -Pattern '^\$AppVersion\s*=\s*"([^"]+)"' | | |
| Select-Object -First 1 | |
| if (-not $m) { Write-Host 'cannot find $AppVersion in tools/build.ps1'; exit 1 } | |
| $version = $m.Matches[0].Groups[1].Value | |
| Write-Host "tools/build.ps1 version: $version" | |
| if ('${{ github.ref_type }}' -eq 'tag') { | |
| $tag = '${{ github.ref_name }}' -replace '^v', '' | |
| if ($tag -ne $version) { | |
| Write-Host ('tag "{0}" does not match $AppVersion "{1}".' -f '${{ github.ref_name }}', $version) | |
| Write-Host 'Bump $AppVersion in tools/build.ps1, or retag.' | |
| exit 1 | |
| } | |
| Write-Host "tag matches" | |
| } else { | |
| Write-Host "manual run - no tag to verify" | |
| } | |
| "APP_VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 | |
| - name: Bootstrap | |
| shell: pwsh | |
| run: ./tools/bootstrap.ps1 | |
| - name: Desktop test suite | |
| shell: pwsh | |
| run: ./tools/test.ps1 | |
| # -Env production is not optional here: the default is Telegram's test | |
| # data centres, which hold no real accounts. An auth_key is bound to one | |
| # environment, so a test-DC build cannot be fixed at runtime. | |
| - name: Build J2MEgram | |
| shell: pwsh | |
| env: | |
| TG_API_ID: ${{ secrets.TG_API_ID }} | |
| TG_API_HASH: ${{ secrets.TG_API_HASH }} | |
| run: ./tools/build.ps1 -Target tg -Env production -ArtifactName "J2MEgram-$env:APP_VERSION" | |
| # Smaller JAR for handsets that cap install size, at the cost of readable | |
| # stack traces in bug reports. | |
| - name: Build J2MEgram (min) | |
| shell: pwsh | |
| env: | |
| TG_API_ID: ${{ secrets.TG_API_ID }} | |
| TG_API_HASH: ${{ secrets.TG_API_HASH }} | |
| run: ./tools/build.ps1 -Target tg -Env production -Release -ArtifactName "J2MEgram-$env:APP_VERSION-min" | |
| # Both published variants must still start. Obfuscation is checked | |
| # statically at build time, but a static check is not a run, and this is | |
| # the last point before the artifacts are public. | |
| - name: Emulator smoke test | |
| shell: pwsh | |
| run: ./tools/smoke-emulator.ps1 -SkipBuild -ArtifactName "J2MEgram-${env:APP_VERSION}","J2MEgram-${env:APP_VERSION}-min" -JavaArgs -Xmx32m | |
| - name: Verify JAD/JAR consistency | |
| shell: pwsh | |
| run: | | |
| $bad = $false | |
| foreach ($jad in Get-ChildItem dist -Filter *.jad) { | |
| $text = Get-Content $jad.FullName -Raw | |
| $url = ([regex]::Match($text, 'MIDlet-Jar-URL:\s*(.+)')).Groups[1].Value.Trim() | |
| $size = [int]([regex]::Match($text, 'MIDlet-Jar-Size:\s*(\d+)')).Groups[1].Value | |
| $jar = Join-Path $jad.DirectoryName $url | |
| if (-not (Test-Path $jar)) { | |
| Write-Host "$($jad.Name): MIDlet-Jar-URL '$url' does not exist"; $bad = $true; continue | |
| } | |
| $actual = (Get-Item $jar).Length | |
| # A single byte of disagreement here and the handset aborts the | |
| # install with an error that names nothing useful. | |
| if ($actual -ne $size) { | |
| Write-Host "$($jad.Name): MIDlet-Jar-Size $size but $url is $actual bytes"; $bad = $true; continue | |
| } | |
| Write-Host "$($jad.Name) -> $url ($actual bytes) OK" | |
| } | |
| if ($bad) { exit 1 } | |
| - name: Checksums | |
| shell: pwsh | |
| run: | | |
| $lines = Get-ChildItem dist -File | | |
| Where-Object { $_.Extension -in '.jar', '.jad' } | | |
| Sort-Object Name | | |
| ForEach-Object { "{0} {1}" -f (Get-FileHash $_ -Algorithm SHA256).Hash.ToLower(), $_.Name } | |
| # LF, not CRLF. Set-Content would write CRLF, and sha256sum -c then | |
| # reads the trailing CR as part of the filename and fails to open | |
| # every single entry - on the Linux and macOS machines where anyone | |
| # is actually going to run it. | |
| [IO.File]::WriteAllText( | |
| (Join-Path $PWD.Path 'dist\SHA256SUMS.txt'), | |
| ($lines -join "`n") + "`n") | |
| $lines | Write-Host | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: midlets | |
| path: | | |
| dist/J2MEgram-*.jar | |
| dist/J2MEgram-*.jad | |
| dist/SHA256SUMS.txt | |
| release: | |
| needs: build | |
| if: github.ref_type == 'tag' | |
| runs-on: ubuntu-latest | |
| steps: | |
| # No name: filter, so every artifact lands under dist/<artifact-name>/. | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: dist | |
| - name: Publish GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: dist/**/* | |
| generate_release_notes: true | |
| body: | | |
| J2MEgram ${{ github.ref_name }} — Telegram over MTProto 2.0, directly on a Java ME phone. | |
| ### Install | |
| Download **both** files of one variant into the **same folder**, copy that | |
| folder to the phone (USB, Bluetooth or memory card), then open the `.jad` | |
| in the phone's file manager. If the handset refuses the `.jad`, open the | |
| `.jar` instead — most will install it directly. | |
| | Variant | Use | | |
| |---|---| | |
| | `J2MEgram-*.jar` + `.jad` | Start here. Crash reports name real classes, which is useful while the client is this young. | | |
| | `J2MEgram-*-min.jar` + `.jad` | Optimised and obfuscated — noticeably smaller. Try it if your phone rejects the normal build as too large. | | |
| The `.jad` records the exact byte size of its `.jar`, so do not rename | |
| either file and do not mix files from different variants or releases. | |
| Installing over the air by opening the release link in the phone's browser | |
| will not work: GitHub needs modern TLS, which these handsets do not have. | |
| Verify downloads against `SHA256SUMS.txt`. | |
| > **This has run on four physical handsets** — an Alcatel OT-810D, a | |
| > Samsung GT-C3592, a Nokia C3-00 and a Nokia E6-00 — where signing in, | |
| > the dialog list and sending a message all work. Four devices on a | |
| > handful of networks prove nothing about yours: compatibility, | |
| > performance and permission behaviour elsewhere are still unknown, so | |
| > reports are genuinely useful — especially your handset model and what | |
| > `J2MEgram Probe` shows. | |
| > Per-device measurements are written up under `docs/hardware/`. | |
| > | |
| > If the direct routes are refused with `Target port denied to untrusted | |
| > applications`, that is the handset's policy for unsigned MIDlets on ports | |
| > 80 and 443, not a bug. Other ports may still be allowed, so configuring an | |
| > MTProxy in Settings before the first connection attempt is worth trying. | |
| > | |
| > **Set the phone's clock before connecting through an MTProxy.** A FakeTLS | |
| > proxy secret embeds the client's time in its handshake, so a wrong clock | |
| > is refused by the proxy and surfaces as an opaque TLS alert. One of the | |
| > four handsets resets its clock to 2011 on every power cycle, which is | |
| > how this was found. | |
| J2MEgram is an independent project. It is not affiliated with or | |
| endorsed by Telegram, and it is not a security-audited everyday client. |