Initial code from ChatGPT
This commit is contained in:
parent
40e3e8f7b8
commit
1b1aa7f65d
|
|
@ -0,0 +1,80 @@
|
||||||
|
name: Build Avida-ED Onefile
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
ed_versions:
|
||||||
|
description: "Comma-separated versions (v3,v4)"
|
||||||
|
default: "v3,v4"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-22.04, windows-2022, macos-13]
|
||||||
|
ver: [v3, v4]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Rust
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- name: Fetch assets via docker compose (using URL fallback on mac/win if docker unavailable)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if command -v docker >/dev/null 2>&1; then
|
||||||
|
docker compose run --rm fetch-${{ matrix.ver }}
|
||||||
|
else
|
||||||
|
MODE=url URL=https://avida-ed.msu.edu/app4/ OUTDIR=./apps/${{ matrix.ver }} bash tools/fetch_assets.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Inject webroot
|
||||||
|
run: |
|
||||||
|
rm -rf server-ui/webroot
|
||||||
|
mkdir -p server-ui/webroot
|
||||||
|
rsync -a apps/${{ matrix.ver }}/Avida-ED-Eco/ server-ui/webroot/Avida-ED-Eco/
|
||||||
|
|
||||||
|
- name: Build binary
|
||||||
|
run: |
|
||||||
|
cd server-ui
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
- name: Package (Linux AppImage)
|
||||||
|
if: startsWith(matrix.os, 'ubuntu')
|
||||||
|
run: |
|
||||||
|
sudo apt-get update && sudo apt-get install -y imagemagick || true
|
||||||
|
bash packaging/linux/make_appimage.sh ${{ matrix.ver }} server-ui/target/release/avidaed_onefile
|
||||||
|
mv Avida-ED-${{ matrix.ver }}-Linux-x86_64.AppImage Avida-ED-${{ matrix.ver }}-Linux-x86_64.AppImage
|
||||||
|
|
||||||
|
- name: Package (Windows EXE)
|
||||||
|
if: startsWith(matrix.os, 'windows')
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
$WV2 = "$env:RUNNER_TEMP\WebView2Fixed" # pre-cached in your org, or downloaded here
|
||||||
|
# TODO: fetch/unzip WebView2 Fixed into $WV2 if not cached
|
||||||
|
powershell -ExecutionPolicy Bypass -File packaging/windows/make_windows_sfx.ps1 `
|
||||||
|
-Version ${{ matrix.ver }} `
|
||||||
|
-BinPath server-ui/target/release/avidaed_onefile.exe `
|
||||||
|
-WV2Fixed $WV2
|
||||||
|
Move-Item packaging\windows\Avida-ED-${{ matrix.ver }}-Windows.exe .
|
||||||
|
|
||||||
|
- name: Package (macOS .app)
|
||||||
|
if: startsWith(matrix.os, 'macos')
|
||||||
|
run: |
|
||||||
|
bash packaging/mac/make_macos_bundle.sh ${{ matrix.ver }} server-ui/target/release/avidaed_onefile
|
||||||
|
# Optionally make a DMG
|
||||||
|
# brew install create-dmg
|
||||||
|
# create-dmg "Avida-ED-${{ matrix.ver }}.app"
|
||||||
|
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Avida-ED-${{ matrix.ver }}-${{ matrix.os }}
|
||||||
|
path: |
|
||||||
|
*.AppImage
|
||||||
|
*.exe
|
||||||
|
Avida-ED-${{ matrix.ver }}.app
|
||||||
|
if-no-files-found: ignore
|
||||||
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
VER ?= v4 # or v3
|
||||||
|
|
||||||
|
.PHONY: fetch-$(VER) inject-$(VER) build-linux build-mac build-win appimage winexe macapp all
|
||||||
|
|
||||||
|
fetch-v3:
|
||||||
|
docker compose run --rm fetch-v3
|
||||||
|
fetch-v4:
|
||||||
|
docker compose run --rm fetch-v4
|
||||||
|
|
||||||
|
inject-$(VER):
|
||||||
|
rm -rf server-ui/webroot
|
||||||
|
mkdir -p server-ui/webroot
|
||||||
|
rsync -a apps/$(VER)/Avida-ED-Eco/ server-ui/webroot/Avida-ED-Eco/
|
||||||
|
|
||||||
|
# Build binaries natively on each OS runner
|
||||||
|
build-linux: inject-$(VER)
|
||||||
|
cd server-ui && cargo build --release
|
||||||
|
|
||||||
|
build-mac: inject-$(VER)
|
||||||
|
cd server-ui && cargo build --release
|
||||||
|
|
||||||
|
build-win: inject-$(VER)
|
||||||
|
cd server-ui && cargo build --release
|
||||||
|
|
||||||
|
# Package
|
||||||
|
appimage: build-linux
|
||||||
|
bash packaging/linux/make_appimage.sh $(VER) server-ui/target/release/avidaed_onefile
|
||||||
|
|
||||||
|
winexe: build-win
|
||||||
|
# Example: pass location of WebView2 Fixed runtime and built exe
|
||||||
|
powershell -ExecutionPolicy Bypass -File packaging/windows/make_windows_sfx.ps1 \
|
||||||
|
-Version $(VER) \
|
||||||
|
-BinPath $(CURDIR)/server-ui/target/release/avidaed_onefile.exe \
|
||||||
|
-WV2Fixed "C:\SDKs\WebView2.FixedRuntime"
|
||||||
|
|
||||||
|
macapp: build-mac
|
||||||
|
bash packaging/mac/make_macos_bundle.sh $(VER) server-ui/target/release/avidaed_onefile
|
||||||
|
|
||||||
|
all:
|
||||||
|
@echo "Targets:"
|
||||||
|
@echo " make fetch-v3 | fetch-v4"
|
||||||
|
@echo " make build-linux | build-mac | build-win"
|
||||||
|
@echo " make appimage | winexe | macapp"
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
version: "3.8"
|
||||||
|
services:
|
||||||
|
fetch-v3:
|
||||||
|
build: { context: ./tools, dockerfile: Dockerfile.fetch }
|
||||||
|
environment:
|
||||||
|
MODE: "docker" # or "url"
|
||||||
|
ED_VER: "v3"
|
||||||
|
OUTDIR: "/out"
|
||||||
|
volumes:
|
||||||
|
- ./apps/v3:/out
|
||||||
|
# If MODE=url, also pass URL as env
|
||||||
|
|
||||||
|
fetch-v4:
|
||||||
|
build: { context: ./tools, dockerfile: Dockerfile.fetch }
|
||||||
|
environment:
|
||||||
|
MODE: "docker"
|
||||||
|
ED_VER: "v4"
|
||||||
|
OUTDIR: "/out"
|
||||||
|
volumes:
|
||||||
|
- ./apps/v4:/out
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
HERE="$(dirname "$(readlink -f "$0")")"
|
||||||
|
exec "$HERE/usr/bin/avidaed_onefile"
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
FROM ubuntu:22.04
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
build-essential curl git libgtk-3-dev libayatana-appindicator3-dev \
|
||||||
|
libwebkit2gtk-4.0-dev pkg-config cmake patchelf desktop-file-utils \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
# appimagetool
|
||||||
|
RUN curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o /usr/local/bin/appimagetool \
|
||||||
|
&& chmod +x /usr/local/bin/appimagetool
|
||||||
|
WORKDIR /work
|
||||||
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Avida-ED
|
||||||
|
Exec=AppRun
|
||||||
|
Type=Application
|
||||||
|
Icon=avidaed
|
||||||
|
Categories=Education;Science;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
VER="${1:?version folder, e.g., v4}"
|
||||||
|
BINPATH="${2:-../..//server-ui/target/release/avidaed_onefile}"
|
||||||
|
|
||||||
|
APPDIR="AvidaED-${VER}.AppDir"
|
||||||
|
rm -rf "$APPDIR"; mkdir -p "$APPDIR/usr/bin" "$APPDIR/usr/share/icons/hicolor/256x256/apps"
|
||||||
|
cp "$BINPATH" "$APPDIR/usr/bin/avidaed_onefile"
|
||||||
|
cp "$(dirname "$0")/AppRun" "$APPDIR/AppRun"
|
||||||
|
chmod +x "$APPDIR/AppRun"
|
||||||
|
cp "$(dirname "$0")/desktop/avidaed.desktop" "$APPDIR/avidaed.desktop"
|
||||||
|
|
||||||
|
# placeholder icon; replace with your PNG
|
||||||
|
convert -size 256x256 xc:white "$APPDIR/usr/share/icons/hicolor/256x256/apps/avidaed.png" 2>/dev/null || true
|
||||||
|
|
||||||
|
appimagetool "$APPDIR" "Avida-ED-${VER}-Linux-x86_64.AppImage"
|
||||||
|
echo "Wrote Avida-ED-${VER}-Linux-x86_64.AppImage"
|
||||||
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleName</key><string>Avida-ED</string>
|
||||||
|
<key>CFBundleDisplayName</key><string>Avida-ED</string>
|
||||||
|
<key>CFBundleIdentifier</key><string>org.avidaed.{{VER}}</string>
|
||||||
|
<key>CFBundleVersion</key><string>1.0</string>
|
||||||
|
<key>CFBundleShortVersionString</key><string>1.0</string>
|
||||||
|
<key>CFBundleExecutable</key><string>Avida-ED</string>
|
||||||
|
<key>LSMinimumSystemVersion</key><string>10.13</string>
|
||||||
|
<key>NSHighResolutionCapable</key><true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
VER="${1:?v3|v4}"
|
||||||
|
BINPATH="${2:-../../server-ui/target/release/avidaed_onefile}"
|
||||||
|
APP="Avida-ED-${VER}.app"
|
||||||
|
rm -rf "$APP"
|
||||||
|
mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources"
|
||||||
|
cp "$BINPATH" "$APP/Contents/MacOS/Avida-ED"
|
||||||
|
chmod +x "$APP/Contents/MacOS/Avida-ED"
|
||||||
|
# Info.plist
|
||||||
|
sed "s/{{VER}}/${VER}/g" "$(dirname "$0")/Info.plist.tmpl" > "$APP/Contents/Info.plist"
|
||||||
|
# Icon placeholder
|
||||||
|
sips -s format icns /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/GenericApplicationIcon.icns --out "$APP/Contents/Resources/AppIcon.icns" >/dev/null 2>&1 || true
|
||||||
|
echo "Wrote $APP (unsigned)."
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][string]$Version, # v3 or v4
|
||||||
|
[Parameter(Mandatory=$true)][string]$BinPath, # path to target\release\avidaed_onefile.exe
|
||||||
|
[Parameter(Mandatory=$true)][string]$WV2Fixed # path to WebView2 Fixed Runtime folder
|
||||||
|
)
|
||||||
|
$Work = Join-Path $PSScriptRoot "payload_$Version"
|
||||||
|
Remove-Item $Work -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
New-Item -ItemType Directory -Force -Path $Work | Out-Null
|
||||||
|
Copy-Item $BinPath -Destination (Join-Path $Work "avidaed_onefile.exe")
|
||||||
|
Copy-Item $WV2Fixed -Destination (Join-Path $Work "WebView2Fixed") -Recurse
|
||||||
|
|
||||||
|
# launcher
|
||||||
|
$runbat = @"
|
||||||
|
@echo off
|
||||||
|
setlocal
|
||||||
|
set WEBVIEW2_BROWSER_EXECUTABLE_FOLDER=%~dp0WebView2Fixed
|
||||||
|
start "" "%~dp0avidaed_onefile.exe"
|
||||||
|
"@
|
||||||
|
$runbat | Out-File -Encoding ASCII (Join-Path $Work "run.bat")
|
||||||
|
|
||||||
|
# create 7z archive
|
||||||
|
$SevenZip = "C:\Program Files\7-Zip\7z.exe"
|
||||||
|
& $SevenZip a -t7z (Join-Path $PSScriptRoot "payload_$Version.7z") "$Work\*"
|
||||||
|
|
||||||
|
# concatenate SFX + config + archive -> one EXE
|
||||||
|
$Sfx = Join-Path $PSScriptRoot "7z.sfx"
|
||||||
|
$Cfg = Join-Path $PSScriptRoot "config.txt"
|
||||||
|
$Out = Join-Path $PSScriptRoot ("Avida-ED-$Version-Windows.exe")
|
||||||
|
Get-Content $Sfx -Encoding Byte, $Cfg -Encoding Byte, (Join-Path $PSScriptRoot "payload_$Version.7z") -Encoding Byte |
|
||||||
|
Set-Content $Out -Encoding Byte
|
||||||
|
Write-Host "Wrote $Out"
|
||||||
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
;!@Install@!UTF-8!
|
||||||
|
Title="Avida-ED"
|
||||||
|
BeginPrompt="Install and run Avida-ED?"
|
||||||
|
RunProgram="run.bat"
|
||||||
|
; extract to temp folder
|
||||||
|
ExtractTitle="Avida-ED"
|
||||||
|
GUIMode="2"
|
||||||
|
;!@InstallEnd@!
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
[package]
|
||||||
|
name = "avidaed_onefile"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wry = "0.39" # WebView wrapper: WebView2/WKWebView/WebKitGTK
|
||||||
|
tiny-http = "0.12" # tiny static server
|
||||||
|
include_dir = "0.7" # embed webroot into binary
|
||||||
|
mime_guess = "2.0"
|
||||||
|
once_cell = "1.19"
|
||||||
|
anyhow = "1.0"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
strip = "symbols"
|
||||||
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=webroot");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
use include_dir::{include_dir, Dir};
|
||||||
|
use tiny_http::{Request, Response, Method};
|
||||||
|
use wry::{
|
||||||
|
application::event::{Event, StartCause, WindowEvent},
|
||||||
|
application::event_loop::{ControlFlow, EventLoop},
|
||||||
|
application::window::WindowBuilder,
|
||||||
|
webview::WebViewBuilder
|
||||||
|
};
|
||||||
|
use std::{net::TcpListener, thread, time::Duration};
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
static WEBROOT: Dir = include_dir!("$CARGO_MANIFEST_DIR/webroot");
|
||||||
|
static DEFAULT_PATH: &str = "/Avida-ED-Eco/index.html";
|
||||||
|
|
||||||
|
fn mime(p: &str)->&'static str{
|
||||||
|
if p.ends_with(".wasm"){return "application/wasm";}
|
||||||
|
if p.ends_with(".js"){return "application/javascript";}
|
||||||
|
if p.ends_with(".css"){return "text/css";}
|
||||||
|
if p.ends_with(".html") || p.ends_with(".htm"){return "text/html; charset=utf-8";}
|
||||||
|
mime_guess::from_path(p).first_raw().unwrap_or("application/octet-stream")
|
||||||
|
}
|
||||||
|
fn serve(mut req:Request){
|
||||||
|
if req.method()!=&Method::Get && req.method()!=&Method::Head{
|
||||||
|
let _=req.respond(Response::from_string("Method Not Allowed").with_status_code(405));return;
|
||||||
|
}
|
||||||
|
let mut path=req.url().to_string();
|
||||||
|
if let Some(i)=path.find('?'){path.truncate(i);}
|
||||||
|
if path=="/"{path=DEFAULT_PATH.to_string();}
|
||||||
|
let fpath=path.trim_start_matches('/');
|
||||||
|
if let Some(f)=WEBROOT.get_file(fpath){
|
||||||
|
let mut resp=Response::from_data(f.contents().to_vec());
|
||||||
|
let _=resp.add_header(tiny_http::Header::from_bytes(b"Content-Type", mime(&path)).unwrap());
|
||||||
|
let _=resp.add_header(tiny_http::Header::from_bytes(b"Cache-Control", b"no-store").unwrap());
|
||||||
|
let _=req.respond(resp);
|
||||||
|
}else{
|
||||||
|
let _=req.respond(Response::from_string("Not Found").with_status_code(404));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn main()->Result<()>{
|
||||||
|
let listener=TcpListener::bind(("127.0.0.1",0))?; listener.set_nonblocking(true)?;
|
||||||
|
let port=listener.local_addr()?.port(); let srv=tiny_http::Server::from_tcp(listener)?;
|
||||||
|
std::thread::spawn(move||{
|
||||||
|
loop{
|
||||||
|
match srv.recv_timeout(Duration::from_millis(200)){
|
||||||
|
Ok(Some(r))=>serve(r), Ok(None)=>continue, Err(_)=>break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let url=format!("http://127.0.0.1:{port}{DEFAULT_PATH}");
|
||||||
|
let event_loop=EventLoop::new()?;
|
||||||
|
let window=WindowBuilder::new()
|
||||||
|
.with_title("Avida-ED")
|
||||||
|
.with_inner_size(wry::application::dpi::LogicalSize::new(1280.0,800.0))
|
||||||
|
.build(&event_loop)?;
|
||||||
|
let _wv=WebViewBuilder::new(&window)?.with_url(&url)?.build()?;
|
||||||
|
event_loop.run(move|e,_,cf|{
|
||||||
|
*cf=wry::application::event_loop::ControlFlow::Wait;
|
||||||
|
if let Event::WindowEvent{event:WindowEvent::CloseRequested,..}=e{*cf=wry::application::event_loop::ControlFlow::Exit;}
|
||||||
|
if let Event::NewEvents(StartCause::Init)=e{}
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
FROM alpine:3.20
|
||||||
|
RUN apk add --no-cache ca-certificates curl bash rsync
|
||||||
|
WORKDIR /work
|
||||||
|
COPY fetch_assets.sh /work/fetch_assets.sh
|
||||||
|
ENTRYPOINT ["/work/fetch_assets.sh"]
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
MODE="${MODE:-docker}" # docker|url
|
||||||
|
ED_VER="${ED_VER:-v4}" # v3|v4
|
||||||
|
OUTDIR="${OUTDIR:-/out}"
|
||||||
|
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
case "$MODE" in
|
||||||
|
docker)
|
||||||
|
# 1) Start your aed-docker container and copy its served webroot
|
||||||
|
# Expectation: container serves Avida-ED-Eco at /usr/share/nginx/html/Avida-ED-Eco
|
||||||
|
CID="$(docker create --name aedtmp_$ED_VER welsberr/aed-docker:$ED_VER)"
|
||||||
|
trap 'docker rm -f aedtmp_'"$ED_VER"' >/dev/null 2>&1 || true' EXIT
|
||||||
|
docker cp "aedtmp_$ED_VER:/usr/share/nginx/html/." "$OUTDIR/"
|
||||||
|
;;
|
||||||
|
url)
|
||||||
|
URL="${URL:-https://avida-ed.msu.edu/app4/}"
|
||||||
|
apk add --no-cache wget >/dev/null 2>&1 || true
|
||||||
|
wget --recursive --no-parent --page-requisites --adjust-extension \
|
||||||
|
--compression=auto --convert-links --timestamping \
|
||||||
|
--directory-prefix "$OUTDIR" \
|
||||||
|
"$URL"
|
||||||
|
# normalize into $OUTDIR/Avida-ED-Eco as needed
|
||||||
|
if [ ! -d "$OUTDIR/Avida-ED-Eco" ]; then
|
||||||
|
SUB="$(find "$OUTDIR" -type f -name index.html | head -n1)"
|
||||||
|
[ -n "$SUB" ] && rsync -a "$(dirname "$SUB")"/ "$OUTDIR/Avida-ED-Eco"/
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*) echo "Unknown MODE=$MODE" >&2; exit 1;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "Assets fetched to $OUTDIR"
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
use std::{env, fs, path::Path};
|
||||||
|
fn main() {
|
||||||
|
let args:Vec<String>=env::args().collect();
|
||||||
|
if args.len()!=3{eprintln!("usage: inject_webroot <src_dir> <dst_dir>"); std::process::exit(2);}
|
||||||
|
let (src,dst)=(&args[1],&args[2]);
|
||||||
|
if Path::new(dst).exists(){fs::remove_dir_all(dst).ok();}
|
||||||
|
fs::create_dir_all(dst).unwrap();
|
||||||
|
fs_extra::dir::copy(src,dst,&fs_extra::dir::CopyOptions{overwrite:true,copy_inside:true, ..Default::default()}).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue